#ifdef ARCTIC
/**
 @file sys_at_queue_enq.c

 @date 2021-8-13

 @version v1.0

 The file contains AT QoS queue APIs of sys layer
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "sys_usw_common.h"
#include "sys_usw_chip.h"
#include "sys_usw_qos.h"
#include "sys_at_qos.h"
#include "sys_usw_dmps.h"
#include "sys_usw_stats.h"
#include "sys_usw_stats_api.h"
#include "sys_usw_port_api.h"
#include "drv_api.h"

#define SYS_QOS_QUEUE_NORMAL_EXCP 0
#define SYS_REASON_NOR_REP_BIT_WIDTH (DRV_FROM_AT(lchip) ? 3 : 0)

#define SYS_AT_QUEUE_ENQ_MODE_TC   0
#define SYS_AT_QUEUE_ENQ_MODE_PRI  1
#define SYS_AT_QUEUE_ENQ_MODE_XPI  2
#define SYS_AT_QUEUE_ENQ_MODE_CPU_PRIO 3
#define SYS_AT_QUEUE_ENQ_MODE_CTL  4
#define SYS_AT_QUEUE_ENQ_MODE_DSTID3_PRI4 5
#define SYS_AT_QUEUE_ENQ_MODE_DSTID 6
#define SYS_AT_QUEUE_ENQ_MODE_DSTID4_PRI3 7
#define SYS_AT_QUEUE_ENQ_REP_QUEUE_SELECT_MAX 5

extern int32
sys_usw_dma_get_packet_rx_chan(uint8 lchip, uint16* p_num);
extern int32
sys_usw_cpu_reason_set_map(uint8 lchip, uint16 reason_id,
                                  uint8 sub_queue_id,
                                  uint8 group_id,
                                  uint8 acl_match_group,
                                  sys_cpu_reason_dest_info_t *p_dest_info);
extern int32
sys_usw_cpu_reason_set_dest(uint8 lchip, uint16 reason_id, sys_cpu_reason_dest_info_t* dest_info);
extern int32
_sys_usw_qos_set_queue_reason_misc(uint8 lchip, ctc_qos_group_cpu_reason_misc_t* p_cpu_reason_misc_para);
extern int32
sys_usw_cpu_reason_get_map(uint8 lchip, uint16 reason_id, uint8* sub_queue_id, uint8* group_id, uint8* acl_match_group);
extern int32
_sys_usw_qos_get_queue_reason_misc(uint8 lchip, ctc_qos_group_cpu_reason_misc_t* p_cpu_reason_misc_para);
extern int32
_sys_at_queue_set_queue_flush_en(uint8 lchip, uint16 sub_chan, sys_queue_node_t* p_queue_node, uint8 ofst, uint8 enable);
extern int32
sys_at_queue_get_queue_min(uint8 lchip, ctc_qos_resrc_queue_min_t* queue_min);
extern int32
sys_at_queue_set_queue_min(uint8 lchip, ctc_qos_resrc_queue_min_t queue_min);
extern int32
sys_at_queue_get_port_min(uint8 lchip, ctc_qos_resrc_port_min_t *port_min);
extern int32
sys_at_queue_set_port_min(uint8 lchip, ctc_qos_resrc_port_min_t *port_min);
extern int32
sys_at_resrc_set_que_drop(uint8 lchip, uint8 is_dynamic, uint8 enable, ctc_qos_drop_t* que_drop, void* p_queue);
extern int32
sys_at_resrc_get_que_drop(uint8 lchip, void* p_sys_queue_node, void* p_sys_drop, uint8 wred_mode,  uint8* wtd_en, uint8* wred_en);
extern uint32
sys_at_qos_get_corss_core_tbl_idx(uint8 lchip, uint8 cur_pp_id, uint8 query_pp_id, uint32 shift);
extern uint32
sys_at_qos_get_corss_core_lchip(uint8* lchip_tmp, uint8 cur_pp_id, uint8 query_pp_id);
STATIC int32
_sys_at_queue_enq_profile_spool_add(uint8 lchip, sys_queue_enq_profile_t* p_prof, sys_queue_enq_profile_t* p_prof_old, sys_queue_enq_profile_t** p_prof_out);
int32
_sys_at_queue_enq_profile_restore(sys_queue_enq_profile_t* p_prof, void* user_data);
int32
_sys_at_queue_enq_profile_alloc(sys_queue_enq_profile_t* p_prof, void* user_data);
STATIC int32
_sys_at_queue_get_erm_profile_id(uint8 lchip, uint16 channel, uint8* ermprofid, uint8* ermprofid_mc);
STATIC int32
_sys_at_qos_queue_map_db_restore(uint8 lchip, uint16 queue_base, sys_queue_node_t *p_node, uint8 is_restore);
STATIC int32
_sys_at_qos_queue_map_port_flexq_db(uint8 lchip, uint16 queue_base, ctc_qos_queue_map_t* que_map, uint8* mod_mcq_new);
STATIC int32
_sys_at_qos_queue_map_port_flexq_hw(uint8 lchip, uint16 queue_base, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map);


#define __QUEUE__

STATIC int32
_sys_at_queue_vec_free_node_data(void* node_data, void* user_data)
{
    mem_free(node_data);

    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_wb_restore_queue_vec(uint8 lchip)
{
    sys_queue_node_t *p_queue_node = NULL;
    sys_queue_enq_profile_t enq_prof_uc;
    sys_queue_enq_profile_t enq_prof_mc;
    DsQMgrQueIdMap_m qid_map;
    DsQMgrQueSchMap_m q_sch_map;
    DsQMgrQueIdReMap_m qid_remap;
    DsUcQueueMap_m ucq_map;
    DsMcQueueMap_m mcq_map;
    uint32 cmd = 0;
    uint32 cos_node_sched = 0;
    uint16 loop = 0;
    uint16 loop2 = 0;
    uint16 pp_chan = 0;
    uint16 pp_que_base = 0;
    uint16 cos_sel_bmp = 0;
    uint16 node_sel_bmp = 0;
    uint8  mc_queue_use = 0;
    uint8 lchip_tmp = lchip;
    uint8 is_uc = 0;
    uint8 q_ofst = 0;
    uint8 sch_ofst = 0;
    uint8 ermprofid_uc = 0;
    uint8 ermprofid_mc = 0;
    uint8 index = 0;

    for (loop = 0; loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM); loop++)
    {
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, loop);
        if (NULL == p_queue_node || SYS_QUEUE_TYPE_NORMAL != p_queue_node->type)
        {
            continue;
        }
        if (0 == loop % MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN))
        {
            mc_queue_use = 0;
            /*restore enq profile*/
            sal_memset(&enq_prof_uc, 0, sizeof(enq_prof_uc));
            sal_memset(&enq_prof_mc, 0, sizeof(enq_prof_mc));
            p_usw_queue_master[lchip]->enq_prof_spool->spool_alloc = (spool_alloc_fn)_sys_at_queue_enq_profile_restore;
            CTC_ERROR_RETURN(_sys_at_queue_get_erm_profile_id(lchip, p_queue_node->sub_chan, &ermprofid_uc, &ermprofid_mc));
            for (loop2 = 0; loop2 < SYS_QUE_MAP_TYPE_MAX_NUM; loop2++)
            {
                index = loop2 << 3 | ermprofid_mc;
                cmd = DRV_IOR(DsMcQueueMap_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcq_map));
                enq_prof_mc.map[loop2].enq_mode = GetDsMcQueueMap(V, queueOffsetMode_f, &mcq_map);
                q_ofst = GetDsMcQueueMap(V, queueOffset_f, &mcq_map); /*ucq_offset[5:2]+ucq_offset[1:0]*/
                enq_prof_mc.map[loop2].offset = q_ofst > 3 ? ((q_ofst >> 2) + (q_ofst & 0x3)) : q_ofst;
                if (enq_prof_mc.map[loop2].enq_mode)
                {
                    CTC_BIT_SET(mc_queue_use, q_ofst > 3 ? ((q_ofst >> 2) + (q_ofst & 0x3)) : q_ofst);
                }

                index = loop2 << 3 | ermprofid_uc;
                cmd = DRV_IOR(DsUcQueueMap_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ucq_map));
                enq_prof_uc.map[loop2].enq_mode = GetDsUcQueueMap(V, queueOffsetMode_f, &ucq_map);
                q_ofst = GetDsUcQueueMap(V, queueOffset_f, &ucq_map);/*ucq_offset[5:2]+ucq_offset[1:0]*/
                enq_prof_uc.map[loop2].offset = q_ofst > 3 ? ((q_ofst >> 2) + (q_ofst & 0x3)) : q_ofst;
            }
            enq_prof_mc.prof_id = ermprofid_mc;
            enq_prof_mc.is_mc = 1;
            enq_prof_uc.prof_id = ermprofid_uc;
            enq_prof_uc.is_mc = 0;
            CTC_ERROR_RETURN(_sys_at_queue_enq_profile_spool_add(lchip, &enq_prof_uc, NULL, NULL));
            CTC_ERROR_RETURN(_sys_at_queue_enq_profile_spool_add(lchip, &enq_prof_mc, NULL, NULL));
            p_usw_queue_master[lchip]->enq_prof_spool->spool_alloc = (spool_alloc_fn)_sys_at_queue_enq_profile_alloc;

            pp_chan = p_queue_node->sub_chan + p_queue_node->dp_id * MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
            pp_que_base = pp_chan * MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
            SYS_QOS_LCHIP_CONVERT(lchip_tmp, p_queue_node->pp_id);
            cmd = DRV_IOR(DsQMgrQueSchMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_chan, DRV_CMD_PP_EN(cmd), &q_sch_map));
            cos_sel_bmp = GetDsQMgrQueSchMap(V, cosSel_f, &q_sch_map);
            node_sel_bmp = GetDsQMgrQueSchMap(V, nodeSel_f, &q_sch_map);
            cmd = DRV_IOR(DsQMgrGrpConfig_t, DsQMgrGrpConfig_schModeCosNode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip_tmp, pp_chan, DRV_CMD_PP_EN(cmd), &cos_node_sched));
        }
        sal_memset(p_queue_node->node, 0, sizeof(p_queue_node->node));
        cmd = DRV_IOR(DsQMgrQueIdReMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_que_base + p_queue_node->offset, DRV_CMD_PP_EN(cmd), &qid_remap));
        is_uc = GetDsQMgrQueIdReMap(V, isUc_f, &qid_remap);
        q_ofst = GetDsQMgrQueIdReMap(V, queOffset_f, &qid_remap);

        cmd = DRV_IOR(DsQMgrQueIdMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_chan * 18 + (is_uc ? 0 : 12) + q_ofst, DRV_CMD_PP_EN(cmd), &qid_map));
        sch_ofst = GetDsQMgrQueIdMap(V, schOffset_f, &qid_map);
        if (!CTC_IS_BIT_SET(cos_sel_bmp, sch_ofst) && sch_ofst == p_queue_node->offset)
        {
            p_queue_node->node[1].type = is_uc ? SYS_QUE_OFST_UC : SYS_QUE_OFST_MC;
            p_queue_node->node[1].ofst = q_ofst;
        }

        if (p_queue_node->offset && CTC_IS_BIT_SET(cos_sel_bmp, p_queue_node->offset - 1))
        {
            cmd = DRV_IOR(DsQMgrQueIdReMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_que_base + p_queue_node->offset - 1, DRV_CMD_PP_EN(cmd), &qid_remap));
            p_queue_node->node[0].type = GetDsQMgrQueIdReMap(V, isUc_f, &qid_remap) ? SYS_QUE_OFST_UC : SYS_QUE_OFST_MC;
            p_queue_node->node[0].ofst = GetDsQMgrQueIdReMap(V, queOffset_f, &qid_remap);
        }

        if (SYS_QUE_OFST_MC == p_queue_node->node[0].type && !CTC_IS_BIT_SET(mc_queue_use,p_queue_node->node[0].ofst))
        {
            p_queue_node->node[0].qdrop_en = 1;
        }
        else if (SYS_QUE_OFST_MC == p_queue_node->node[1].type && !CTC_IS_BIT_SET(mc_queue_use,p_queue_node->node[1].ofst))
        {
            p_queue_node->node[1].qdrop_en = 1;
        }

        p_queue_node->class_prio = CTC_IS_BIT_SET(node_sel_bmp, p_queue_node->offset) ? 1 : 0;
        p_queue_node->sched_mode = CTC_IS_BIT_SET(cos_node_sched, p_queue_node->offset)
                                   ? CTC_QOS_SCHED_MODE_SP : CTC_QOS_SCHED_MODE_WDRR;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_check_queue_status(uint8 lchip, sys_queue_node_t* p_queue_node, uint8 ofst)
{
    uint32 depth = 0;
    uint32 index = 0;
    uint32 loop = 0;
    uint32 cmd = 0;
    DsErmQueueCntMc_m erm_cnt_mc;
    DsErmQueueCntUc_m erm_cnt_uc;

    /*get sub chan by queue id*/
    SYS_QOS_LCHIP_CONVERT(lchip, p_queue_node->pp_id);

    /*check queue flush clear*/
    do
    {
        depth = 0;
        if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
        {
            index = SYS_AT_QOS_ENCOD_DP_QUE_UC(p_queue_node->sub_chan, p_queue_node->node[ofst].ofst);
            cmd = DRV_IOR(DsErmQueueCntUc_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, p_queue_node->dp_id), &erm_cnt_uc));
            depth += GetDsErmQueueCntUc(V, queueCnt_f, &erm_cnt_uc);
            if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
            {
                uint8 _dual_core_lchip = 0;
                SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip, _dual_core_lchip);
                CTC_ERROR_RETURN(DRV_IOCTL(_dual_core_lchip, DRV_INS(1, index), DRV_CMD_DP_EN(cmd, p_queue_node->dp_id), &erm_cnt_uc));
                depth += GetDsErmQueueCntUc(V, queueCnt_f, &erm_cnt_uc);
            }
        }
        else if (SYS_QUE_OFST_MC == p_queue_node->node[ofst].type)
        {
            index = SYS_AT_QOS_ENCOD_CORE_QUE_MC(p_queue_node->sub_chan, p_queue_node->pp_id, p_queue_node->dp_id, p_queue_node->node[ofst].ofst);
            cmd = DRV_IOR(DsErmQueueCntMc_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &erm_cnt_mc));
            depth += GetDsErmQueueCntMc(V, g_0_queueCnt_f, &erm_cnt_mc);
            depth += GetDsErmQueueCntMc(V, g_1_queueCnt_f, &erm_cnt_mc);
            if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
            {
                uint8 _dual_core_lchip = 0;
                SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip, _dual_core_lchip);
                CTC_ERROR_RETURN(DRV_IOCTL(_dual_core_lchip, index + DRV_TABLE_MAX_INDEX(lchip, DsErmQueueCntMc_t) / 2, DRV_CMD_PP_EN(cmd), &erm_cnt_mc));
                depth += GetDsErmQueueCntMc(V, g_0_queueCnt_f, &erm_cnt_mc);
                depth += GetDsErmQueueCntMc(V, g_1_queueCnt_f, &erm_cnt_mc);
            }
        }

        if(!depth)
        {
            return CTC_E_NONE;
        }
        sal_task_sleep(1);

    }while((loop++) <= 1000);

    return CTC_E_HW_TIME_OUT;
}

STATIC int32
_sys_at_qos_queue_get_lport_by_sub_chan(uint8 lchip, uint8 pp_id, uint8 dp_id, uint8 sub_chan, uint16* lport)
{
    ds_t ds;
    IpeHeaderAdjustPhyPortMap_m phy_port_map;
    uint32 cmd = 0;
    uint16 channel = 0;

    *lport = 0;
    cmd = DRV_IOR(IpeHeaderAdjustChannelPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(SYS_PP_BASE(lchip) + pp_id, sub_chan, DRV_CMD_PP_EN(cmd), &ds));
    channel = dp_id ? GetIpeHeaderAdjustChannelPortMap(V, g_1_ppSrcPort_f, &ds)
                    : GetIpeHeaderAdjustChannelPortMap(V, g_0_ppSrcPort_f, &ds);
    if (channel)
    {
        cmd = DRV_IOR(IpeHeaderAdjustPhyPortMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel, cmd, &phy_port_map));
        *lport = GetIpeHeaderAdjustPhyPortMap(V, localPhyPort_f, &phy_port_map);
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_set_queue_flush(uint8 lchip, ctc_qos_queue_com_t* p_queue_flush)
{
    uint16 queue_id = 0;
    uint16 lport = 0;
    uint8  i = 0;
    uint8  ofst = 0;
    int32 ret = CTC_E_NONE;
    sys_queue_node_t* p_sys_queue_node = NULL;

    ctc_qos_resrc_queue_min_t queue_min_tmp;
    ctc_qos_drop_t queue_drop_tmp;
    ctc_qos_resrc_port_min_t port_min_tmp;

    ctc_qos_resrc_queue_min_t queue_min[12];
    ctc_qos_drop_t queue_drop;
    ctc_qos_resrc_port_min_t port_min[2];

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if(p_queue_flush->queue.queue_type != CTC_QUEUE_TYPE_NETWORK_EGRESS)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_IS_MCHAN_PORT(p_queue_flush->queue.gport))
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Normal Gport with muti-channel not support queue flush \n");
        return CTC_E_NOT_SUPPORT;
    }

    CTC_MAX_VALUE_CHECK(p_queue_flush->queue.class_prio, SYS_QUEUE_SUB_NODE_NUM-1);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_queue_flush->queue.gport, lchip, lport);

    sal_memset(&queue_min_tmp, 0, sizeof(ctc_qos_resrc_queue_min_t));
    sal_memset(&queue_drop_tmp, 0, sizeof(ctc_qos_drop_t));
    sal_memset(&port_min_tmp, 0, sizeof(ctc_qos_resrc_port_min_t));

    sal_memset(&queue_drop, 0, sizeof(ctc_qos_drop_t));
    sal_memset(&port_min, 0, sizeof(ctc_qos_resrc_port_min_t) * 2);
    sal_memset(&queue_min, 0, sizeof(ctc_qos_resrc_queue_min_t) * 12);

    CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip,  &p_queue_flush->queue, &queue_id));

    p_sys_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_sys_queue_node)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    /*1. get user cfg*/
    /*1.1 get queue guarantee*/
    for (i=0;i<MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);i++)
    {
        sal_memcpy(&(queue_min[i].queue), &(p_queue_flush->queue), sizeof(ctc_qos_queue_id_t));
        queue_min[i].queue.queue_id = i;
        CTC_ERROR_RETURN(sys_at_queue_get_queue_min(lchip, &(queue_min[i])));
    }

    /*1.2 get queue limit*/
    sal_memcpy(&(queue_drop.queue), &(p_queue_flush->queue), sizeof(ctc_qos_queue_id_t));
    CTC_ERROR_RETURN(sys_at_resrc_get_que_drop(lchip, p_sys_queue_node, &queue_drop, 0, NULL, NULL));

    /*1.3 get port guarantee*/
    port_min[0].gport = p_queue_flush->queue.gport;
    port_min[0].dir = CTC_EGRESS;
    port_min[0].non_uc = 0;
    CTC_ERROR_RETURN(sys_at_queue_get_port_min(lchip, &(port_min[0])));
    port_min[1].gport = p_queue_flush->queue.gport;
    port_min[1].dir = CTC_EGRESS;
    port_min[1].non_uc = 1;
    CTC_ERROR_RETURN(sys_at_queue_get_port_min(lchip, &(port_min[1])));

    /*2. set queue guarantee and queue limit*/
    sal_memcpy(&(queue_min_tmp.queue), &(p_queue_flush->queue), sizeof(ctc_qos_queue_id_t));
    queue_min_tmp.threshold = SYS_AT_PORT_MIN_GUARANTEE;
    for (i=0;i<MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);i++)
    {
        queue_min_tmp.queue.queue_id = i;
        queue_min_tmp.threshold = (i == p_queue_flush->queue.queue_id) ? 0 : queue_min_tmp.threshold;
        CTC_ERROR_RETURN(sys_at_queue_set_queue_min(lchip, queue_min_tmp));
    }

    sal_memcpy(&(queue_drop_tmp.queue), &(p_queue_flush->queue), sizeof(ctc_qos_queue_id_t));
    CTC_ERROR_RETURN(sys_at_resrc_set_que_drop(lchip, 0, 1, &queue_drop_tmp, p_sys_queue_node));

    /*3. set port guarantee*/
    port_min_tmp.gport = p_queue_flush->queue.gport;
    port_min_tmp.dir = CTC_EGRESS;
    port_min_tmp.non_uc = 0;
    CTC_ERROR_RETURN(sys_at_queue_set_port_min(lchip, &port_min_tmp));
    port_min_tmp.non_uc = 1;
    CTC_ERROR_RETURN(sys_at_queue_set_port_min(lchip, &port_min_tmp));

    ofst = SYS_AT_COS_SUB_NODE_OFST(p_sys_queue_node, p_queue_flush->queue.class_prio);
    /*4. enable queue flush*/
    CTC_ERROR_RETURN(_sys_at_queue_set_queue_flush_en(lchip, 0, p_sys_queue_node, ofst, TRUE));

    /*5. check flush done*/
    ret = _sys_at_qos_check_queue_status(lchip, p_sys_queue_node, ofst);

    /*6. disable queue flush*/
    CTC_ERROR_RETURN(_sys_at_queue_set_queue_flush_en(lchip, 0, p_sys_queue_node, ofst, FALSE));

    /*7. restore user cfg*/
    /*7.1 restore queue guarantee*/
    for (i=0;i<MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);i++)
    {
        CTC_ERROR_RETURN(sys_at_queue_set_queue_min(lchip, queue_min[i]));
    }

    /*7.2 restore queue limit*/
    CTC_ERROR_RETURN(sys_at_resrc_set_que_drop(lchip, queue_drop.drop.is_dynamic, 1, &queue_drop, p_sys_queue_node));

    /*7.3 restore port guarantee*/
    CTC_ERROR_RETURN(sys_at_queue_set_port_min(lchip, &(port_min[0])));
    CTC_ERROR_RETURN(sys_at_queue_set_port_min(lchip, &(port_min[1])));

    return ret;
}

uint32
_sys_at_queue_enq_profile_hash_make(sys_queue_enq_profile_t* p_prof)
{
    return ctc_hash_caculate(SYS_QUE_MAP_TYPE_MAX_NUM * sizeof(sys_queue_type_maping_t), p_prof) + p_prof->is_mc;
}

int32
_sys_at_queue_enq_profile_hash_cmp(sys_queue_enq_profile_t* p_prof1, sys_queue_enq_profile_t* p_prof2)
{
    if (!p_prof1 || !p_prof2)
    {
        return FALSE;
    }
    if (p_prof1->is_mc != p_prof2->is_mc)
    {
        return FALSE;
    }
    if (!sal_memcmp(p_prof1, p_prof2, SYS_QUE_MAP_TYPE_MAX_NUM * sizeof(sys_queue_type_maping_t)))
    {
        return TRUE;
    }
    return FALSE;
}

int32
_sys_at_queue_enq_profile_restore(sys_queue_enq_profile_t* p_prof, void* user_data)
{
    uint8 lchip = *(uint8*)user_data;
    CTC_BIT_SET(p_usw_queue_master[lchip]->enq_prof_bmp, p_prof->prof_id + (p_prof->is_mc * SYS_ERM_PROFILE_MAX_NUM));
    return CTC_E_NONE;
}

int32
_sys_at_queue_enq_profile_alloc(sys_queue_enq_profile_t* p_prof, void* user_data)
{
    uint32 cmd = 0;
    DsUcQueueMap_m ucq_map;
    DsMcQueueMap_m mcq_map;
    uint8 lchip = *(uint8*)user_data;
    uint8 prof_id = 0;
    uint8 index = 0;
    uint8 qmaptype = 0;
    uint8 offset = 0;
    do
    {
        if (!CTC_IS_BIT_SET(p_usw_queue_master[lchip]->enq_prof_bmp, prof_id + (p_prof->is_mc * SYS_ERM_PROFILE_MAX_NUM)) && prof_id)
        {
            break;
        }
    } while (++prof_id < SYS_ERM_PROFILE_MAX_NUM);
    if (prof_id == SYS_ERM_PROFILE_MAX_NUM)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "enq profile id alloc failed.\n");
        return -1;
    }
    p_prof->prof_id = prof_id;
    /*set hw map table*/
    sal_memset(&ucq_map, 0, sizeof(DsUcQueueMap_m));
    sal_memset(&mcq_map, 0, sizeof(DsMcQueueMap_m));

    for (qmaptype = 0; qmaptype < SYS_QUE_MAP_TYPE_MAX_NUM; qmaptype++)
    {
        index = qmaptype << 3 | prof_id;
        offset = (p_prof->map[qmaptype].offset > 3)
                            ? (((p_prof->map[qmaptype].offset - 3) << 2) | 0x3)
                            : p_prof->map[qmaptype].offset;
        if (p_prof->is_mc)
        {
            SetDsMcQueueMap(V, queueOffsetMode_f, &mcq_map, p_prof->map[qmaptype].enq_mode);
            SetDsMcQueueMap(V, queueOffset_f, &mcq_map, offset); /*ucq_offset[5:2]+ucq_offset[1:0]*/
            cmd = DRV_IOW(DsMcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcq_map));
            /*fabric*/
            cmd = DRV_IOW(DsMcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index | 0x40, cmd, &mcq_map));
        }
        else
        {
            SetDsUcQueueMap(V, queueOffsetMode_f, &ucq_map, p_prof->map[qmaptype].enq_mode);
            SetDsUcQueueMap(V, queueOffset_f, &ucq_map, offset);/*ucq_offset[5:2]+ucq_offset[1:0]*/
            cmd = DRV_IOW(DsUcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ucq_map));
            /*fabric*/
            cmd = DRV_IOW(DsUcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index | 0x40, cmd, &ucq_map));
        }
    }
    CTC_BIT_SET(p_usw_queue_master[lchip]->enq_prof_bmp, prof_id + (p_prof->is_mc * SYS_ERM_PROFILE_MAX_NUM));
    return 0;
}

int32
_sys_at_queue_enq_profile_free(sys_queue_enq_profile_t* p_prof, void* user_data)
{
    uint32 cmd = 0;
    DsUcQueueMap_m ucq_map;
    DsMcQueueMap_m mcq_map;
    uint8 lchip = *(uint8*)user_data;
    uint8 index = 0;
    uint8 qmaptype = 0;

    CTC_BIT_UNSET(p_usw_queue_master[lchip]->enq_prof_bmp, p_prof->prof_id + (p_prof->is_mc * SYS_ERM_PROFILE_MAX_NUM));
    /*unset hw map table*/
    sal_memset(&ucq_map, 0, sizeof(DsUcQueueMap_m));
    sal_memset(&mcq_map, 0, sizeof(DsMcQueueMap_m));

    for (qmaptype = 0; qmaptype < SYS_QUE_MAP_TYPE_MAX_NUM; qmaptype++)
    {
        index = qmaptype << 3 | p_prof->prof_id;
        if (p_prof->is_mc)
        {
            cmd = DRV_IOW(DsMcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcq_map));
            /*fabric*/
            cmd = DRV_IOW(DsMcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index | 0x40, cmd, &mcq_map));
        }
        else
        {
            cmd = DRV_IOW(DsUcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ucq_map));
            /*fabric*/
            cmd = DRV_IOW(DsUcQueueMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index | 0x40, cmd, &ucq_map));
        }
    }
    return 0;
}

STATIC int32
_sys_at_queue_enq_profile_spool_add(uint8 lchip, sys_queue_enq_profile_t* p_prof, sys_queue_enq_profile_t* p_prof_old, sys_queue_enq_profile_t** p_prof_out)
{
    return ctc_spool_add(p_usw_queue_master[lchip]->enq_prof_spool, p_prof, p_prof_old, (void*)p_prof_out);
}

STATIC int32
_sys_at_queue_enq_profile_spool_remove(uint8 lchip, sys_queue_enq_profile_t* p_prof, sys_queue_enq_profile_t** p_prof_out)
{
    return ctc_spool_remove(p_usw_queue_master[lchip]->enq_prof_spool, p_prof, (void*)p_prof_out);
}

STATIC int32
_sys_at_queue_set_erm_profile_id(uint8 lchip, uint16 channel, uint8 ermprofid, uint8 ermprofid_mc)
{
    uint32 cmd = 0;
    uint8 bmp = 0x40;
    uint16 pp_bmp = 0;
    uint8 index = 0;
    uint8 core_num = drv_vchip_get_core_num(lchip);
    uint8 per_core_pp_num = (2 == core_num) ? drv_vchip_get_pp_num(lchip) / 2 : drv_vchip_get_pp_num(lchip);
    uint16 sub_chan = 0;
    DsUcQWriteChannel_m qwrite_channel;
    DsMcQWriteChannel_m qwrite_channel_mc;

    sal_memset(&qwrite_channel, 0, sizeof(qwrite_channel));
    sal_memset(&qwrite_channel_mc, 0, sizeof(qwrite_channel_mc));
    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    lchip = drv_vchip_get_pp_base(lchip);
    for (index = 0; index < per_core_pp_num; index++)
    {
        CTC_BIT_SET(pp_bmp, index);
    }
    bmp = 0x40 | (pp_bmp << 2); /*core 0 */
    SetDsUcQWriteChannel(V, queueMapProfId_f, &qwrite_channel, ermprofid);
    cmd = DRV_IOW(DsUcQWriteChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, sub_chan, (((uint64)bmp << 32) | cmd), &qwrite_channel));
    SetDsMcQWriteChannel(V, queueMapProfId_f, &qwrite_channel_mc, ermprofid_mc);
    cmd = DRV_IOW(DsMcQWriteChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, sub_chan, (((uint64)bmp << 32) | cmd), &qwrite_channel_mc));

    if (2 == core_num)
    {
        lchip = drv_vchip_get_pp_base(lchip) + per_core_pp_num;
        bmp = 0x80 | (pp_bmp << 2);/*core 1*/
        if (sub_chan & 0x100)
        {
            sub_chan &= 0xFF;/*for core1 to core1, should set bit8 = 0, means core1 self*/
        }
        else
        {
            sub_chan |= 0x100; /*for core1 to core0, should set bit8 = 1, means cross core*/
        }
        cmd = DRV_IOW(DsUcQWriteChannel_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, sub_chan, (((uint64)bmp << 32) | cmd), &qwrite_channel));
        cmd = DRV_IOW(DsMcQWriteChannel_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL_BMP(lchip, sub_chan, (((uint64)bmp << 32) | cmd), &qwrite_channel_mc));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_get_erm_profile_id(uint8 lchip, uint16 channel, uint8* ermprofid, uint8* ermprofid_mc)
{
    uint32 cmd = 0;
    DsUcQWriteChannel_m qwrite_channel;
    DsMcQWriteChannel_m qwrite_channel_mc;
    uint16 sub_chan = 0;

    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    lchip = drv_vchip_get_pp_base(lchip);
    cmd = DRV_IOR(DsUcQWriteChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, cmd, &qwrite_channel));
    *ermprofid = GetDsUcQWriteChannel(V, queueMapProfId_f, &qwrite_channel);
    cmd = DRV_IOR(DsMcQWriteChannel_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, sub_chan, cmd, &qwrite_channel_mc));
    *ermprofid_mc = GetDsMcQWriteChannel(V, queueMapProfId_f, &qwrite_channel_mc);

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "sub_chan = %d, uc_enq_profid = %d, mc_enq_profid = %d\n", sub_chan, *ermprofid, *ermprofid_mc);
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_add_static_profile(uint8 lchip, sys_queue_enq_profile_t* enq_prof, sys_queue_enq_profile_t* enq_prof_mc)
{
    DsUcQueueMap_m ucq_map;
    DsMcQueueMap_m mcq_map;
    uint32 cmd = 0;
    uint8 qmaptype = 0;
    uint8 index = 0;
    uint8 offset = 0;

    sal_memset(&ucq_map, 0, sizeof(DsUcQueueMap_m));
    sal_memset(&mcq_map, 0, sizeof(DsMcQueueMap_m));

    /*static profile id is 0*/
    CTC_ERROR_RETURN(ctc_spool_static_add(p_usw_queue_master[lchip]->enq_prof_spool, enq_prof));
    CTC_ERROR_RETURN(ctc_spool_static_add(p_usw_queue_master[lchip]->enq_prof_spool, enq_prof_mc));

    /*set hw map table*/
    for (qmaptype = 0; qmaptype < SYS_QUE_MAP_TYPE_MAX_NUM; qmaptype++)
    {
        index = qmaptype << 3 | enq_prof_mc->prof_id;
        offset = (enq_prof_mc->map[qmaptype].offset > 3) ? (((enq_prof_mc->map[qmaptype].offset - 3) << 2) | 0x3) : enq_prof_mc->map[qmaptype].offset;
        SetDsMcQueueMap(V, queueOffsetMode_f, &mcq_map, enq_prof_mc->map[qmaptype].enq_mode);
        SetDsMcQueueMap(V, queueOffset_f, &mcq_map, offset); /*mcq_offset[5:2]+mcq_offset[1:0]*/
        cmd = DRV_IOW(DsMcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcq_map));
        /*fabric*/
        cmd = DRV_IOW(DsMcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index | 0x40, cmd, &mcq_map));

        index = qmaptype << 3 | enq_prof->prof_id;
        offset = (enq_prof->map[qmaptype].offset > 3) ? (((enq_prof->map[qmaptype].offset - 3) << 2) | 0x3) : enq_prof->map[qmaptype].offset;
        SetDsUcQueueMap(V, queueOffsetMode_f, &ucq_map, enq_prof->map[qmaptype].enq_mode);
        SetDsUcQueueMap(V, queueOffset_f, &ucq_map, offset);/*ucq_offset[5:2]+ucq_offset[1:0]*/
        cmd = DRV_IOW(DsUcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ucq_map));
        /*fabric*/
        cmd = DRV_IOW(DsUcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index | 0x40, cmd, &ucq_map));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_add_static_fix_profile(uint8 lchip)
{
    sys_queue_enq_profile_t enq_prof;
    sys_queue_enq_profile_t enq_prof_mc;

    sal_memset(&enq_prof, 0, sizeof(sys_queue_enq_profile_t));
    sal_memset(&enq_prof_mc, 0, sizeof(sys_queue_enq_profile_t));

    enq_prof.map[SYS_QUE_MAP_TYPE_CPU_PKT].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof.map[SYS_QUE_MAP_TYPE_CPU_PKT].offset = 7;
    enq_prof.map[SYS_QUE_MAP_TYPE_C2C].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof.map[SYS_QUE_MAP_TYPE_C2C].offset = 8;
    enq_prof.prof_id = 0;

    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UC].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UC].offset = 1;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_MC].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_MC].offset = 1;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_SPAN].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_SPAN].offset = 0;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_CPU_PKT].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_CPU_PKT].offset = 1;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_C2C].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_C2C].offset = 2;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UNKNOWN_MC].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UNKNOWN_MC].offset = 0;
    enq_prof_mc.is_mc = 1;
    enq_prof_mc.prof_id = 0;  

    CTC_ERROR_RETURN(_sys_at_queue_add_static_profile(lchip, &enq_prof, &enq_prof_mc));
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_alloc_enq_prof_id(uint8 lchip, uint16 queue_base,
                                    ctc_qos_queue_map_t* que_map,
                                    sys_queue_enq_profile_t** p_prof_uc,
                                    sys_queue_enq_profile_t** p_prof_mc,
                                    sys_queue_enq_profile_t* p_prof_uc_old,
                                    sys_queue_enq_profile_t* p_prof_mc_old)
{
    sys_queue_node_t* p_queue_node = NULL;
    ctc_qos_queue_enq_t* p_enq = NULL;
    sys_queue_enq_profile_t enq_prof;
    sys_queue_enq_profile_t enq_prof_mc;
    int32 ret = 0;
    uint8 idx = 0;
    uint8 ucq_ofst = 0;
    uint8 mcq_ofst = 0;
    uint8 ucq_valid = 0;
    uint8 mcq_valid = 0;
    uint8 enq_mode = 0;

    sal_memset(&enq_prof, 0, sizeof(sys_queue_enq_profile_t));
    sal_memset(&enq_prof_mc, 0, sizeof(sys_queue_enq_profile_t));
    enq_prof_mc.is_mc = 1;
    for (idx = 0; idx < que_map->enq_num; idx++)
    {
        p_enq = &que_map->enq[idx];
        ucq_valid = p_enq->ucq_num;
        mcq_valid = p_enq->mcq_num;
        ucq_ofst = 0;
        mcq_ofst = 0;
    
        if (CTC_QOS_ENQ_MODE_UESER_DEFINE == p_enq->enq_mode)
        {
            p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + p_enq->q_base);
            if (NULL == p_queue_node)
            {
                continue;
            }
            if (SYS_QUE_OFST_UC == p_queue_node->node[0].type && SYS_QUE_OFST_UC == p_queue_node->node[1].type)
            {
                ucq_ofst = p_queue_node->node[p_enq->class_prio].ofst;
            }
            else if (SYS_QUE_OFST_UC == p_queue_node->node[0].type)
            {
                ucq_ofst = p_queue_node->node[0].ofst;
            }
            else if (SYS_QUE_OFST_UC == p_queue_node->node[1].type)
            {
                ucq_ofst = p_queue_node->node[1].ofst;
            }
            if (SYS_QUE_OFST_MC == p_queue_node->node[0].type && SYS_QUE_OFST_MC == p_queue_node->node[1].type)
            {
                mcq_ofst = p_queue_node->node[p_enq->class_prio].ofst;
            }
            else if (SYS_QUE_OFST_MC == p_queue_node->node[0].type)
            {
                mcq_ofst = p_queue_node->node[0].ofst;
            }
            else if (SYS_QUE_OFST_MC == p_queue_node->node[1].type)
            {
                mcq_ofst = p_queue_node->node[1].ofst;
            }
            enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
        }
        else
        {
            enq_mode = SYS_AT_QUEUE_ENQ_MODE_TC;
        }
        if (CTC_FLAG_ISSET(p_enq->pkt_type, CTC_QOS_QUEUE_PKT_TYPE_C2C))
        {
            if (ucq_valid)
            {
                enq_prof.map[SYS_QUE_MAP_TYPE_C2C].enq_mode = enq_mode;
                enq_prof.map[SYS_QUE_MAP_TYPE_C2C].offset = ucq_ofst;
            }
            if (mcq_valid)
            {
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_C2C].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_C2C].offset = mcq_ofst;
            }
        }
        if (CTC_FLAG_ISSET(p_enq->pkt_type, CTC_QOS_QUEUE_PKT_TYPE_CPU))
        {
            if (ucq_valid)
            {
                enq_prof.map[SYS_QUE_MAP_TYPE_CPU_PKT].enq_mode = enq_mode;
                enq_prof.map[SYS_QUE_MAP_TYPE_CPU_PKT].offset = ucq_ofst;
            }
            if (mcq_valid)
            {
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_CPU_PKT].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_CPU_PKT].offset = mcq_ofst;
            }
        }
        if (CTC_FLAG_ISSET(p_enq->pkt_type, CTC_QOS_QUEUE_PKT_TYPE_OAM))
        {
            if (ucq_valid)
            {
                enq_prof.map[SYS_QUE_MAP_TYPE_OAM].enq_mode = enq_mode;
                enq_prof.map[SYS_QUE_MAP_TYPE_OAM].offset = ucq_ofst;
            }
            if (mcq_valid)
            {
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_OAM].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_OAM].offset = mcq_ofst;
            }
        }
        if (CTC_FLAG_ISSET(p_enq->pkt_type, CTC_QOS_QUEUE_PKT_TYPE_SPAN))
        {
            if (ucq_valid)
            {
                enq_prof.map[SYS_QUE_MAP_TYPE_SPAN].enq_mode = enq_mode;
                enq_prof.map[SYS_QUE_MAP_TYPE_SPAN].offset = ucq_ofst;
            }
            if (mcq_valid)
            {
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_SPAN].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_SPAN].offset = mcq_ofst;
            }
        }
        if (CTC_FLAG_ISSET(p_enq->pkt_type, CTC_QOS_QUEUE_PKT_TYPE_UNKNOWN))
        {
            if (mcq_valid)
            {
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_UNKNOWN_MC].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_UNKNOWN_MC].offset = mcq_ofst;
            }
        }
        if (CTC_FLAG_ISSET(p_enq->pkt_type, CTC_QOS_QUEUE_PKT_TYPE_KNOWN))
        {
            if (ucq_valid)
            {
                enq_prof.map[SYS_QUE_MAP_TYPE_UC].enq_mode = enq_mode;
                enq_prof.map[SYS_QUE_MAP_TYPE_UC].offset = ucq_ofst;
            }
            if (mcq_valid)
            {
                /*mcq for uc pkt*/
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_UC].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_UC].offset = mcq_ofst;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_MC].enq_mode = enq_mode;
                enq_prof_mc.map[SYS_QUE_MAP_TYPE_MC].offset = mcq_ofst;
            }
        }
    }

    CTC_ERROR_RETURN(_sys_at_queue_enq_profile_spool_add(lchip, &enq_prof, p_prof_uc_old, p_prof_uc));
    CTC_ERROR_GOTO(_sys_at_queue_enq_profile_spool_add(lchip, &enq_prof_mc, p_prof_mc_old, p_prof_mc), ret, error_back);

    return CTC_E_NONE;
error_back:
    _sys_at_queue_enq_profile_spool_remove(lchip, *p_prof_uc, NULL);
    return ret;
}

STATIC int32
_sys_at_queue_get_enq_prof(uint8 lchip, sys_port_info_t* port_info, sys_queue_enq_profile_t* p_enq_prof, sys_queue_enq_profile_t* p_enq_prof_mc)
{
    DsMcQueueMap_m mcq_map;
    DsUcQueueMap_m ucq_map;
    uint32 cmd = 0;
    uint8 index = 0;
    uint8 qmaptype = 0;
    uint8 ermprofid_uc = 0;
    uint8 ermprofid_mc = 0;
    uint8 enq_mode = 0;
    uint8 offset = 0;
    uint8 q_ofst = 0;

    CTC_ERROR_RETURN(_sys_at_queue_get_erm_profile_id(lchip, port_info->chan_id, &ermprofid_uc, &ermprofid_mc));
    p_enq_prof->prof_id = ermprofid_uc;
    p_enq_prof_mc->prof_id = ermprofid_mc;
    p_enq_prof_mc->is_mc = 1;
    for (qmaptype = 0; qmaptype < SYS_QUE_MAP_TYPE_MAX_NUM; qmaptype++)
    {
        index = qmaptype << 3 | ermprofid_uc;
        cmd = DRV_IOR(DsUcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ucq_map));
        enq_mode = GetDsUcQueueMap(V, queueOffsetMode_f, &ucq_map);
        offset = GetDsUcQueueMap(V, queueOffset_f, &ucq_map);
        q_ofst = (offset >> 2) + (offset & 0x3);
        p_enq_prof->map[qmaptype].enq_mode = enq_mode;
        p_enq_prof->map[qmaptype].offset = q_ofst;

        index = qmaptype << 3 | ermprofid_mc;
        cmd = DRV_IOR(DsMcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcq_map));
        enq_mode = GetDsMcQueueMap(V, queueOffsetMode_f, &mcq_map);
        offset = GetDsMcQueueMap(V, queueOffset_f, &mcq_map);
        q_ofst = (offset >> 2) + (offset & 0x3);
        p_enq_prof_mc->map[qmaptype].enq_mode = enq_mode;
        p_enq_prof_mc->map[qmaptype].offset = q_ofst;
    }
    return CTC_E_NONE;
}

/*default config*/
STATIC int32
_sys_at_queu_set_internal_port_flex_mode(uint8 lchip, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map, sys_queue_enq_profile_t* enq_prof, sys_queue_enq_profile_t* enq_prof_mc)
{
    sys_queue_node_t *p_queue_node = NULL;
    int32 ret = CTC_E_NONE;
    uint16 queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info->sub_chan_id, port_info->pp_id, port_info->dp_id);
    uint8 mod_mcq_new = 0;

    /* queue_vec db store for error roll back */
    p_queue_node = mem_malloc(MEM_QUEUE_MODULE, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) * sizeof(sys_queue_node_t));
    if (NULL == p_queue_node)
    {
        return CTC_E_NO_MEMORY;
    }
    _sys_at_qos_queue_map_db_restore(lchip, queue_base, p_queue_node, 0);
    /* config queue offset map */
    CTC_ERROR_GOTO(_sys_at_qos_queue_map_port_flexq_db(lchip, queue_base, que_map, &mod_mcq_new), ret, error_back);
    /* config queue offset map hw */
    CTC_ERROR_GOTO(_sys_at_qos_queue_map_port_flexq_hw(lchip, queue_base, port_info, que_map), ret, error_back);
    /* attach profile id to channel */
    CTC_ERROR_GOTO(_sys_at_queue_set_erm_profile_id(lchip, port_info->chan_id, enq_prof->prof_id, enq_prof_mc->prof_id), ret, error_back);

    mem_free(p_queue_node);
    return CTC_E_NONE;

error_back:
    _sys_at_qos_queue_map_db_restore(lchip, queue_base, p_queue_node, 1);
    mem_free(p_queue_node);
return ret;
}

STATIC int32
_sys_at_queue_set_internal_enq_prof_id(uint8 lchip)
{
    DsQMgrGrpConfig_m grp_config;
    sys_queue_enq_profile_t enq_prof;
    sys_queue_enq_profile_t enq_prof_mc;
    sys_port_info_t port_info;
    ctc_qos_queue_map_t internal_map;
    ctc_qos_queue_enq_t enq[8];
    int32 ret = CTC_E_NONE;
    uint32 cmd     = 0;
    uint16 channel = 0;
    uint8  pp_chan = 0;
    uint8  lchip_tmp = lchip;
    uint8  index = 0;

    sal_memset(&enq_prof, 0, sizeof(sys_queue_enq_profile_t));
    sal_memset(&enq_prof_mc, 0, sizeof(sys_queue_enq_profile_t));
    sal_memset(&port_info, 0, sizeof(sys_port_info_t));
    sal_memset(&enq, 0, 8 * sizeof(ctc_qos_queue_enq_t));
    sal_memset(&internal_map, 0, sizeof(ctc_qos_queue_map_t));

    enq_prof.map[SYS_QUE_MAP_TYPE_CPU_PKT].enq_mode = SYS_AT_QUEUE_ENQ_MODE_DSTID;
    enq_prof.map[SYS_QUE_MAP_TYPE_CPU_PKT_PRIO].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CPU_PRIO;
    enq_prof.map[SYS_QUE_MAP_TYPE_C2C].enq_mode = SYS_AT_QUEUE_ENQ_MODE_DSTID3_PRI4;
    enq_prof.prof_id = 1;

    enq_prof_mc.is_mc = 1;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UC].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UC].offset = 1;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_MC].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_MC].offset = 1;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_SPAN].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_SPAN].offset = 2;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_CPU_PKT].enq_mode = SYS_AT_QUEUE_ENQ_MODE_DSTID;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_CPU_PKT_PRIO].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CPU_PRIO;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_C2C].enq_mode = SYS_AT_QUEUE_ENQ_MODE_DSTID4_PRI3;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UNKNOWN_MC].enq_mode = SYS_AT_QUEUE_ENQ_MODE_CTL;
    enq_prof_mc.map[SYS_QUE_MAP_TYPE_UNKNOWN_MC].offset = 1;
    enq_prof_mc.prof_id = 1;

    /*config queue num*/
    enq[0].q_base = 0;
    enq[0].mcq_num = 4;

    enq[1].q_base = 4;
    enq[1].ucq_num = 4;

    enq[2].q_base = 0;
    enq[2].mcq_num = 1;
    enq[2].pkt_type = SYS_QUE_MAP_TYPE_CPU_PKT | SYS_QUE_MAP_TYPE_CPU_PKT_PRIO | SYS_QUE_MAP_TYPE_C2C;
    enq[2].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;

    enq[3].q_base = 1;
    enq[3].mcq_num = 1;
    enq[3].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_KNOWN | CTC_QOS_QUEUE_PKT_TYPE_UNKNOWN;
    enq[3].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;

    enq[4].q_base = 2;
    enq[4].mcq_num = 1;
    enq[4].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_SPAN;
    enq[4].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;

    enq[5].q_base = 3;
    enq[5].mcq_num = 1;
    enq[5].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_QDROP;
    enq[5].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;

    internal_map.enq = enq;
    internal_map.enq_num = 6;

    CTC_ERROR_RETURN(_sys_at_queue_add_static_profile(lchip, &enq_prof, &enq_prof_mc));

    /*MOD channel enq profile init*/
    ret = sys_usw_port_api_set_other_misc_chan(lchip, MCHIP_CAP(SYS_CAP_RSV_PORT_MOD_ID), SYS_DMPS_MISC_OTHER_PORT, SYS_PORT_SPEED_50G, CTC_EGRESS);
    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, MCHIP_CAP(SYS_CAP_RSV_PORT_MOD_ID), 0, &port_info));
    if (CTC_E_NONE == ret && port_info.chan_id != SYS_COMMON_USELESS_CHANNEL)
    {
        CTC_ERROR_RETURN(_sys_at_queu_set_internal_port_flex_mode(lchip, &port_info, &internal_map, &enq_prof, &enq_prof_mc));
    }

    /*Eunit channel enq profile init*/
    for (index=0; index < MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_NUM_EUNIT); index++)
    {
        port_info.chan_id = MCHIP_CAP(SYS_CAP_CHANID_EUNIT0) + index;
        if (SYS_VCHIP_DUAL_CORE_MODE(lchip) && index >= (MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_NUM_EUNIT) / drv_vchip_get_core_num(lchip)))
        {
            /*core0 pp1 pp2 & core1 pp1 pp2 dp 0 sub_channel 24 for eunit*/
            port_info.pp_id = 1 + index - (MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_NUM_EUNIT) / drv_vchip_get_core_num(lchip)) + (SYS_PP_NUM(lchip) / drv_vchip_get_core_num(lchip));
        }
        else
        {
            /*core0 pp1 pp2 dp 0 sub_channel 24 for eunit*/
            port_info.pp_id = 1 + index;
        }
        port_info.dp_id = 0;
        port_info.sub_chan_id = SYS_DMPS_MISC_SUB_CHAN;
        CTC_ERROR_RETURN(_sys_at_queu_set_internal_port_flex_mode(lchip, &port_info, &internal_map, &enq_prof, &enq_prof_mc));

        pp_chan = SYS_AT_QOS_ENCOD_PP_CHAN(port_info.sub_chan_id, port_info.dp_id);
        SYS_QOS_LCHIP_CONVERT(lchip_tmp, port_info.pp_id);

        cmd = DRV_IOR(DsQMgrGrpConfig_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_chan, DRV_CMD_PP_EN(cmd), &grp_config));
        SetDsQMgrGrpConfig(V, schModeSubNode_f, &grp_config, 0);
        cmd = DRV_IOW(DsQMgrGrpConfig_t, DsQMgrGrpConfig_schModeSubNode_f);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_chan, DRV_CMD_PP_EN(cmd), &grp_config));
    }

    /*DMA channel enq profile init*/
    CTC_ERROR_RETURN(sys_at_get_channel_by_sub_channel(lchip, 0, SYS_DMA_SUB_CHAN, &channel));
    CTC_ERROR_RETURN(_sys_at_queue_set_erm_profile_id(lchip, channel, enq_prof.prof_id, enq_prof_mc.prof_id));

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_port_flexq_db(uint8 lchip, uint16 queue_base, ctc_qos_queue_map_t* que_map, uint8* mod_mcq_new)
{
    sys_queue_node_t  *p_queue_node = NULL;
    ctc_qos_queue_enq_t* p_enq = NULL;
    uint8 que_used[12] = {0};
    uint8 cos_ofst = 0;
    uint8 ucq_ofst = 0;
    uint8 mcq_ofst = 0;
    uint8 idx = 0;

    /* reset old queue node */
    for (cos_ofst = 0; cos_ofst < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); cos_ofst++)
    {
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + cos_ofst);
        if (NULL == p_queue_node)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
            return CTC_E_NOT_EXIST;
        }
        sal_memset(p_queue_node->node, 0, SYS_QUEUE_SUB_NODE_NUM * sizeof(sys_queue_sub_node_t));
    }

    for (idx = 0; idx < que_map->enq_num; idx++)
    {
        p_enq = &que_map->enq[idx];
        if (p_enq->pkt_type)
        {
            p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + p_enq->q_base);
            if (NULL == p_queue_node)
            {
                continue;
            }
            if (CTC_QOS_QUEUE_PKT_TYPE_QDROP == p_enq->pkt_type)
            {
                if (SYS_QUE_OFST_MC == p_queue_node->node[0].type)
                {
                    p_queue_node->node[0].qdrop_en = 1;
                    *mod_mcq_new = p_queue_node->node[0].ofst;
                }
                else if (SYS_QUE_OFST_MC == p_queue_node->node[1].type)
                {
                    p_queue_node->node[1].qdrop_en = 1;
                    *mod_mcq_new = p_queue_node->node[1].ofst;
                }
            }
            continue;
        }

        if (p_enq->q_base && (2 == (p_enq->ucq_num + p_enq->mcq_num)) && 0 == que_used[p_enq->q_base - 1])
        {
            /*one cos bind two node*/
            p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + p_enq->q_base);
            if (NULL == p_queue_node)
            {
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_queue_node->sched_mode = CTC_QOS_SCHED_MODE_WDRR == p_enq->sched_mode ? 1 : 0;
            p_queue_node->class_prio = p_enq->class_prio;
            if (p_enq->ucq_num && p_enq->mcq_num)
            {
                p_queue_node->node[1].ofst = ucq_ofst++;
                p_queue_node->node[1].type = SYS_QUE_OFST_UC;
                p_queue_node->node[0].ofst = mcq_ofst++;
                p_queue_node->node[0].type = SYS_QUE_OFST_MC;
            }
            else if (p_enq->ucq_num)
            {
                p_queue_node->node[0].ofst = ucq_ofst++;
                p_queue_node->node[0].type = SYS_QUE_OFST_UC;
                p_queue_node->node[1].ofst = ucq_ofst++;
                p_queue_node->node[1].type = SYS_QUE_OFST_UC;
            }
            else
            {
                p_queue_node->node[0].ofst = mcq_ofst++;
                p_queue_node->node[0].type = SYS_QUE_OFST_MC;
                p_queue_node->node[1].ofst = mcq_ofst++;
                p_queue_node->node[1].type = SYS_QUE_OFST_MC;
            }
            que_used[p_enq->q_base] = 1;
            que_used[p_enq->q_base - 1] = 1;
        }
        else
        {
            for (cos_ofst = 0; cos_ofst < p_enq->ucq_num + p_enq->mcq_num; cos_ofst++)
            {
                p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + p_enq->q_base + cos_ofst);
                if (NULL == p_queue_node)
                {
                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                    return CTC_E_NOT_EXIST;
                }
                p_queue_node->sched_mode = CTC_QOS_SCHED_MODE_WDRR == p_enq->sched_mode ? 1 : 0;
                p_queue_node->class_prio = p_enq->class_prio;

                if (cos_ofst < p_enq->ucq_num)
                {
                    p_queue_node->node[1].ofst = ucq_ofst++;
                    p_queue_node->node[1].type = SYS_QUE_OFST_UC;
                }
                else
                {
                    p_queue_node->node[1].ofst = mcq_ofst++;
                    p_queue_node->node[1].type = SYS_QUE_OFST_MC;
                }
                que_used[p_enq->q_base + cos_ofst] = 1;
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_port_flexq_hw(uint8 lchip, uint16 queue_base, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map)
{
    sys_queue_node_t  *p_queue_node = NULL;
    DsQMgrQueIdMap_m qid_map;
    DsQMgrQueSchMap_m q_sch_map;
    DsQMgrQueIdReMap_m qid_remap;
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 cos_node_sched = 0;
    uint16 pp_chan = port_info->sub_chan_id + port_info->dp_id * MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
    uint16 pp_que_base = pp_chan * MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
    uint16 cos_sel_bmp = 0;
    uint16 node_sel_bmp = 0;
    uint8 ofst = 0;
    uint8 cos_ofst = 0;
    uint8 lchip_tmp = lchip;

    sal_memset(&qid_map, 0, sizeof(qid_map));
    sal_memset(&q_sch_map, 0, sizeof(q_sch_map));
    sal_memset(&qid_remap, 0, sizeof(qid_remap));
    SYS_QOS_LCHIP_CONVERT(lchip_tmp, port_info->pp_id);

    /* reset old map */
    for (cos_ofst = 0; cos_ofst < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); cos_ofst++)
    {
        SetDsQMgrQueIdReMap(V, isUc_f, &qid_remap, 0);
        SetDsQMgrQueIdReMap(V, queOffset_f, &qid_remap, 0);
        cmd = DRV_IOW(DsQMgrQueIdReMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_que_base + cos_ofst, DRV_CMD_PP_EN(cmd), &qid_remap));
    }
    for (cos_ofst = 0; cos_ofst < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); cos_ofst++)
    {
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + cos_ofst);
        if (NULL == p_queue_node)
        {
            continue;
        }
        if (p_queue_node->class_prio)
        {
            CTC_BIT_SET(node_sel_bmp, cos_ofst);
        }
        if (CTC_QOS_SCHED_MODE_SP == p_queue_node->sched_mode)
        {
            CTC_BIT_SET(cos_node_sched, cos_ofst);
        }
        for (ofst = 0; ofst < SYS_QUEUE_SUB_NODE_NUM; ofst++)
        {
            if (SYS_QUE_OFST_NONE == p_queue_node->node[ofst].type)
            {
                continue;
            }
            if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
            {
                /*uc*/
                index = pp_chan * 18 + p_queue_node->node[ofst].ofst;
            }
            else
            {
                /*mc*/
                index = pp_chan * 18 + 12 + p_queue_node->node[ofst].ofst;
            }
            SetDsQMgrQueIdMap(V, schOffset_f, &qid_map, (0 == ofst && cos_ofst) ? cos_ofst - 1 : cos_ofst);
            cmd = DRV_IOW(DsQMgrQueIdMap0_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, index, DRV_CMD_PP_EN(cmd), &qid_map));
            cmd = DRV_IOW(DsQMgrQueIdMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, index, DRV_CMD_PP_EN(cmd), &qid_map));

            SetDsQMgrQueIdReMap(V, isUc_f, &qid_remap, (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type) ? 1 : 0);
            SetDsQMgrQueIdReMap(V, queOffset_f, &qid_remap, p_queue_node->node[ofst].ofst);
            cmd = DRV_IOW(DsQMgrQueIdReMap_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_que_base + ((0 == ofst && cos_ofst) ? cos_ofst - 1 : cos_ofst), DRV_CMD_PP_EN(cmd), &qid_remap));
            if (0 == ofst && cos_ofst)
            {
                CTC_BIT_SET(cos_sel_bmp, cos_ofst - 1);
            }
        }
    }

    SetDsQMgrQueSchMap(V, cosSel_f, &q_sch_map, cos_sel_bmp);
    SetDsQMgrQueSchMap(V, nodeSel_f, &q_sch_map, node_sel_bmp);
    cmd = DRV_IOW(DsQMgrQueSchMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, pp_chan, DRV_CMD_PP_EN(cmd), &q_sch_map));
    cmd = DRV_IOW(DsQMgrGrpConfig_t, DsQMgrGrpConfig_schModeCosNode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip_tmp, pp_chan, DRV_CMD_PP_EN(cmd), &cos_node_sched));

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_param_check(uint8 lchip, ctc_qos_queue_map_t* que_map)
{
    ctc_qos_queue_enq_t* p_enq = NULL;
    ctc_qos_queue_enq_t *p_enq_last = NULL;
    uint32 pkt_type[12] = {0};
    uint8 que_used[12] = {0}; /* bit0-used, bit1-have_mc bit2-have_uc */
    uint16 ucq_num = 0;
    uint16 mcq_num = 0;
    uint8 idx = 0;
    uint8 cos_ofst = 0;
    uint8 used_mcq_num = 0;

    CTC_MAX_VALUE_CHECK(que_map->enq_num, 2 * MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN));
    CTC_PTR_VALID_CHECK(que_map->enq);
    for (idx = 0; idx < que_map->enq_num; idx++)
    {
        p_enq = &que_map->enq[idx];
        if (0 == (p_enq->ucq_num + p_enq->mcq_num))
        {
            return CTC_E_INVALID_CONFIG;
        }
        if ((MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) - 1) == p_enq->q_base)
        {
            CTC_MAX_VALUE_CHECK(p_enq->q_base + p_enq->ucq_num + p_enq->mcq_num, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) + 1);
        }
        else
        {
            CTC_MAX_VALUE_CHECK(p_enq->q_base + p_enq->ucq_num + p_enq->mcq_num, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN));
        }
        CTC_MAX_VALUE_CHECK(p_enq->sched_mode, CTC_QOS_SCHED_MODE_MAX - 1);
        CTC_MAX_VALUE_CHECK(p_enq->enq_mode, CTC_QOS_ENQ_MODE_MAX - 1);
        CTC_MAX_VALUE_CHECK(p_enq->class_prio, 1);
        if (CTC_QOS_ENQ_MODE_UESER_DEFINE == p_enq->enq_mode
            && (p_enq->ucq_num > 1 || p_enq->mcq_num > 1))
        {
            return CTC_E_INVALID_CONFIG;
        }
        pkt_type[p_enq->q_base] |= p_enq->pkt_type;
        if (CTC_FLAG_ISSET(pkt_type[p_enq->q_base], CTC_QOS_QUEUE_PKT_TYPE_QDROP)
            && (CTC_QOS_QUEUE_PKT_TYPE_QDROP != pkt_type[p_enq->q_base] || !CTC_IS_BIT_SET(que_used[p_enq->q_base], 1)))
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Not suport qdrop enqueue id merge with others, or without mcq.\n");
            return CTC_E_NOT_SUPPORT;
        }

        if (p_enq->pkt_type)
        {
            /* can not config not used cos queue */
            if(!CTC_IS_BIT_SET(que_used[p_enq->q_base], 0)
               || (p_enq->ucq_num && !CTC_IS_BIT_SET(que_used[p_enq->q_base], 2))
               || (p_enq->mcq_num && !CTC_IS_BIT_SET(que_used[p_enq->q_base], 1)))
            {
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Enq idx:%d not match\n",idx);
                return CTC_E_INVALID_PARAM;
            }
            used_mcq_num += p_enq->mcq_num ? 1 : 0;
            continue;
        }
        if (idx)
        {
            p_enq_last = &que_map->enq[idx - 1];
            if (p_enq_last->q_base >= p_enq->q_base)
            {
                return CTC_E_INVALID_CONFIG;
            }
        }
        /*queue base & queue number check*/
        if (2 == (p_enq->ucq_num + p_enq->mcq_num))
        {
            /*one cos bind two node check*/
            if (que_used[p_enq->q_base])
            {
                return CTC_E_INVALID_CONFIG;
            }

            CTC_BIT_SET(que_used[p_enq->q_base], 0);

            if ((MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) - 1) == p_enq->q_base && que_used[p_enq->q_base - 1])
            {
                return CTC_E_INVALID_CONFIG;
            }
            else if ((0 == p_enq->q_base) || que_used[p_enq->q_base - 1])
            {
                CTC_BIT_SET(que_used[p_enq->q_base + 1], 0);
                if(2 == p_enq->mcq_num)
                {
                    CTC_BIT_SET(que_used[p_enq->q_base], 1);
                    CTC_BIT_SET(que_used[p_enq->q_base + 1], 1);
                }
                else if(2 == p_enq->ucq_num)
                {
                    CTC_BIT_SET(que_used[p_enq->q_base], 2);
                    CTC_BIT_SET(que_used[p_enq->q_base + 1], 2);
                }
                else
                {
                    /*parm check should be consistent with build queue node*/
                    CTC_BIT_SET(que_used[p_enq->q_base], 2);
                    CTC_BIT_SET(que_used[p_enq->q_base + 1], 1);
                }
            }
            else
            {
                CTC_BIT_SET(que_used[p_enq->q_base - 1], 0);
                if(p_enq->mcq_num)
                {
                    CTC_BIT_SET(que_used[p_enq->q_base], 1);
                }
                if(p_enq->ucq_num)
                {
                    CTC_BIT_SET(que_used[p_enq->q_base], 2);
                }
            }
        }
        else
        {
            for (cos_ofst = 0; cos_ofst < (p_enq->ucq_num + p_enq->mcq_num); cos_ofst++)
            {
                if (que_used[p_enq->q_base + cos_ofst])
                {
                    return CTC_E_INVALID_CONFIG;
                }
                /*parm check should be consistent with build queue node*/
                CTC_BIT_SET(que_used[p_enq->q_base + cos_ofst], 0);
                CTC_BIT_SET(que_used[p_enq->q_base + cos_ofst], (cos_ofst < p_enq->ucq_num ) ? 2 : 1);
            }
        }
        ucq_num += p_enq->ucq_num;
        mcq_num += p_enq->mcq_num;
    }
    if(used_mcq_num != mcq_num)
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_MAX_VALUE_CHECK(mcq_num, SYS_AT_MC_QUEUE_NUM);
    CTC_MAX_VALUE_CHECK(ucq_num + mcq_num, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN));
    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_mod_conflict_check(uint8 lchip, ctc_qos_queue_map_t* que_map, uint8 mod_mcq_new, uint8 flag)
{
    McQWriteSpanOnDropCtl_m mc_span_ctl;
    sys_port_info_t port_info;
    ctc_port_bitmap_t port_bmp_zero;
    uint32 cmd = 0;
    uint16 channel_id = 0;
    uint16 lport = 0;
    uint8 enable = 0;
    uint8 dp_chan = 0;
    uint8 dp_id = 0;
    uint8 pp_id = 0;

    if(!flag)
    {
        return CTC_E_NONE;
    }
    cmd = DRV_IOR(McQWriteSpanOnDropCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &mc_span_ctl));
    enable = GetMcQWriteSpanOnDropCtl(V, spanOnDropEn_f, &mc_span_ctl);
    if(!enable)
    {
        return CTC_E_NONE;
    }
    sal_memset(&port_info, 0, sizeof(port_info));
    sal_memset(port_bmp_zero, 0, sizeof(port_bmp_zero));
    dp_chan = GetMcQWriteSpanOnDropCtl(V, sodDest_channelId_f, &mc_span_ctl);
    dp_id = GetMcQWriteSpanOnDropCtl(V, sodDest_dpId_f, &mc_span_ctl);
    pp_id = GetMcQWriteSpanOnDropCtl(V, sodDest_ppId_f, &mc_span_ctl);
    CTC_ERROR_RETURN(sys_at_get_channel_by_sub_channel(pp_id, dp_id, dp_chan, &channel_id));
    lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, channel_id);
    if (sal_memcmp(que_map->port_bmp, port_bmp_zero, sizeof(ctc_port_bitmap_t)) ? !CTC_BMP_ISSET(que_map->port_bmp, lport) : lport != CTC_MAP_GPORT_TO_LPORT(que_map->gport))
    {
        return CTC_E_NONE;
    }
    if (mod_mcq_new != GetMcQWriteSpanOnDropCtl(V, sodDest_queueOffset_f, &mc_span_ctl))
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Can not change qdrop enqueue id when mod enable.\n");
        return CTC_E_INVALID_CONFIG;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_db_restore(uint8 lchip, uint16 queue_base, sys_queue_node_t *p_node, uint8 is_restore)
{
    sys_queue_node_t *p_queue_node = NULL;
    uint8 cos_ofst = 0;

    for (cos_ofst = 0; cos_ofst < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); cos_ofst++)
    {
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + cos_ofst);
        if (NULL == p_queue_node)
        {
            continue;
        }
        if (is_restore)
        {
            /*restore db*/
            sal_memcpy(p_queue_node, &p_node[cos_ofst], sizeof(sys_queue_node_t));
        }
        else
        {
            /*store db*/
            sal_memcpy(&p_node[cos_ofst], p_queue_node, sizeof(sys_queue_node_t));
        }
    }
    return CTC_E_NONE;
}


STATIC int32
_sys_at_qos_queue_map_port_flex_mode(uint8 lchip, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map, uint8 flag)
{
    sys_queue_node_t *p_queue_node = NULL;
    sys_queue_enq_profile_t* p_prof_uc = NULL;
    sys_queue_enq_profile_t* p_prof_mc = NULL;
    sys_queue_enq_profile_t prof_uc_old;
    sys_queue_enq_profile_t prof_mc_old;
    int32 ret = 0;
    uint16 queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info->sub_chan_id, port_info->pp_id, port_info->dp_id);
    uint8 mod_mcq_new = CTC_MAX_UINT8_VALUE;
    sal_memset(&prof_uc_old, 0, sizeof(sys_queue_enq_profile_t));
    sal_memset(&prof_mc_old, 0, sizeof(sys_queue_enq_profile_t));
    /* profile check */
    CTC_ERROR_RETURN(_sys_at_qos_queue_map_param_check(lchip, que_map));

    CTC_ERROR_RETURN(_sys_at_queue_get_enq_prof(lchip, port_info, &prof_uc_old, &prof_mc_old));

    /* queue_vec db store for error roll back */
    p_queue_node = mem_malloc(MEM_QUEUE_MODULE, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) * sizeof(sys_queue_node_t));
    if (NULL == p_queue_node)
    {
        return CTC_E_NO_MEMORY;
    }
    _sys_at_qos_queue_map_db_restore(lchip, queue_base, p_queue_node, 0);

    /* config queue offset map */
    CTC_ERROR_GOTO(_sys_at_qos_queue_map_port_flexq_db(lchip, queue_base, que_map, &mod_mcq_new), ret, error_back);
    /* check flexq and mod mcq conflict */
    CTC_ERROR_GOTO(_sys_at_qos_queue_map_mod_conflict_check(lchip, que_map, mod_mcq_new, flag), ret, error_back);
    /* alloc profile id */
    CTC_ERROR_GOTO(_sys_at_queue_alloc_enq_prof_id(lchip, queue_base, que_map, &p_prof_uc, &p_prof_mc, &prof_uc_old, &prof_mc_old), ret, error_back);
    /* config queue offset map hw */
    CTC_ERROR_GOTO(_sys_at_qos_queue_map_port_flexq_hw(lchip, queue_base, port_info, que_map), ret, error_back1);
    /* attach profile id to channel */
    CTC_ERROR_GOTO(_sys_at_queue_set_erm_profile_id(lchip, port_info->chan_id, p_prof_uc->prof_id, p_prof_mc->prof_id), ret, error_back1);

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "queue_base %d, old_uc_prof_id: %d, old_mc_prof_id:%d, new_uc_prof_id: %d, new_mc_prof_id:%d\n",
                                                queue_base, prof_uc_old.prof_id, prof_mc_old.prof_id, p_prof_uc->prof_id, p_prof_mc->prof_id);
    mem_free(p_queue_node);
    return CTC_E_NONE;
error_back1:
    _sys_at_queue_enq_profile_spool_remove(lchip, p_prof_uc, NULL);
    _sys_at_queue_enq_profile_spool_remove(lchip, p_prof_mc, NULL);
error_back:
    _sys_at_qos_queue_map_db_restore(lchip, queue_base, p_queue_node, 1);
    mem_free(p_queue_node);
return ret;
}
int32
_sys_at_qos_queue_map_port_fixed_mode(uint8 lchip, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map, uint8 flag)
{
    ctc_qos_queue_map_t map_9uc_3mc;
    ctc_qos_queue_enq_t enq[9];

    sal_memset(&enq, 0, 9 * sizeof(ctc_qos_queue_enq_t));
    sal_memset(&map_9uc_3mc, 0, sizeof(ctc_qos_queue_map_t));

    /*config queue num*/
    enq[0].q_base = 0;
    enq[0].ucq_num = 8;
    enq[0].class_prio = 1;

    enq[1].q_base = 8;
    enq[1].mcq_num = 2;

    enq[2].q_base = 10;
    enq[2].mcq_num = 1;
    enq[2].class_prio = 1;

    enq[3].q_base = 11;
    enq[3].ucq_num = 1;
    enq[3].class_prio = 1;

    enq[4].q_base = 7;
    enq[4].ucq_num = 1;
    enq[4].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_CPU;
    enq[4].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;
    enq[4].class_prio = 1;

    enq[5].q_base = 8;
    enq[5].mcq_num = 1;
    enq[5].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_UNKNOWN | CTC_QOS_QUEUE_PKT_TYPE_SPAN;
    enq[5].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;

    enq[6].q_base = 9;
    enq[6].mcq_num = 1;
    enq[6].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_KNOWN | CTC_QOS_QUEUE_PKT_TYPE_CPU;
    enq[6].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;

    enq[7].q_base = 10;
    enq[7].mcq_num = 1; /*C2C MC*/
    enq[7].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_C2C;
    enq[7].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;
    enq[7].class_prio = 1;

    enq[8].q_base = 11;
    enq[8].ucq_num = 1;
    enq[8].pkt_type = CTC_QOS_QUEUE_PKT_TYPE_C2C;
    enq[8].enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;
    enq[8].class_prio = 1;

    map_9uc_3mc.enq = enq;
    map_9uc_3mc.enq_num = 9;

    return _sys_at_qos_queue_map_port_flex_mode(lchip, port_info, &map_9uc_3mc, flag);
}

STATIC int32
_sys_at_qos_queue_map_init(uint8 lchip)
{
    sys_port_info_t port_info;
    uint16 lport = 0;

    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); lport++)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, 0, &port_info));
        if (port_info.sub_chan_id == SYS_COMMON_USELESS_CHANNEL)
        {
            continue;
        }
        CTC_ERROR_RETURN(_sys_at_qos_queue_map_port_fixed_mode(lchip, &port_info, NULL, 0));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_reg_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 entry_num = 0;
    uint8 chan_num = 0;
    uint8 group_num = 0;
    uint8 step = 0;
    uint8 i = 0;
    uint8 j = 0;
    uint16 group_vec = 0;
    uint8 grp_num_per_ring = 0;
    UcQWriteCtl_m  quc_write_ctl;
    McQWriteCtl_m  qmc_write_ctl;
    EpeHdrEditToDmaCtl_m epe_to_dma_ctl;
    DmaRxStallMap_m dma_rx_map;
    DsQMgrFlowCtlMap0_m fc_map;
    DsQMgrGrpConfig_m grp_cfg;
    DsUcDestMapXlate_m map_xlate;

    sal_memset(&quc_write_ctl, 0, sizeof(quc_write_ctl));
    sal_memset(&epe_to_dma_ctl, 0, sizeof(epe_to_dma_ctl));
    sal_memset(&dma_rx_map, 0, sizeof(dma_rx_map));
    sal_memset(&fc_map, 0, sizeof(fc_map));
    sal_memset(&grp_cfg, 0, sizeof(grp_cfg));

    /*config QWriteCtl*/
    cmd = DRV_IOR(UcQWriteCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &quc_write_ctl));
    SetUcQWriteCtl(V, cpuPacketQueMapType_f, &quc_write_ctl, SYS_QUE_MAP_TYPE_CPU_PKT);
    SetUcQWriteCtl(V, spanPacketQueMapType_f, &quc_write_ctl, SYS_QUE_MAP_TYPE_SPAN);
    SetUcQWriteCtl(V, cpuFwdPacketQueMapType_f, &quc_write_ctl, SYS_QUE_MAP_TYPE_CPU_PKT_PRIO);
    SetUcQWriteCtl(V, c2cPacketQueMapType_f, &quc_write_ctl, SYS_QUE_MAP_TYPE_C2C);
    SetUcQWriteCtl(V, oamPacketQueMapType_f, &quc_write_ctl, SYS_QUE_MAP_TYPE_OAM);
    SetUcQWriteCtl(V, spanToCpuQueueEn_f, &quc_write_ctl, 0x2);/*bit0:to remote chip,bit1:to local chip*/
    cmd = DRV_IOW(UcQWriteCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &quc_write_ctl));

    cmd = DRV_IOR(McQWriteCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qmc_write_ctl));
    SetMcQWriteCtl(V, cpuPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_CPU_PKT);
    SetMcQWriteCtl(V, unkownPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_UNKNOWN_MC);
    SetMcQWriteCtl(V, knownMcPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_MC);
    SetMcQWriteCtl(V, spanPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_SPAN);
    SetMcQWriteCtl(V, cpuFwdPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_CPU_PKT_PRIO);
    SetMcQWriteCtl(V, c2cPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_C2C);
    SetMcQWriteCtl(V, oamPacketQueMapType_f, &qmc_write_ctl, SYS_QUE_MAP_TYPE_OAM);
    SetMcQWriteCtl(V, spanToCpuQueueEn_f, &qmc_write_ctl, 0x2);/*bit0:to remote chip,bit1:to local chip*/
    cmd = DRV_IOW(McQWriteCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qmc_write_ctl));

    /*config group node sp*/
    SetDsQMgrGrpConfig(V, schModeSubNode_f, &grp_cfg, 0x3);
    sys_usw_ftm_query_table_entry_num(lchip, DsQMgrGrpConfig_t, &entry_num);
    cmd = DRV_IOW(DsQMgrGrpConfig_t, DRV_ENTRY_FLAG);
    for (i = 0; i < entry_num; i++)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, i, cmd, &grp_cfg));
    }
    CTC_ERROR_RETURN(_sys_at_qos_queue_map_init(lchip));
    /*reset DMA channel and MOD channel ermProfile*/
    CTC_ERROR_RETURN(_sys_at_queue_set_internal_enq_prof_id(lchip));

    /*config queue group select dma ring*/
    chan_num = p_usw_queue_master[lchip]->max_dma_rx_num; /*mean dma ring*/
    group_num = p_usw_queue_master[lchip]->queue_num_for_cpu_reason / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
    grp_num_per_ring = group_num / chan_num;
    for (i = 0; i < group_num; i++)
    {
        step = EpeHdrEditToDmaCtl_g_1_dmaChanId_f - EpeHdrEditToDmaCtl_g_0_dmaChanId_f;
        SetEpeHdrEditToDmaCtl(V, g_0_dmaChanId_f + step * i, &epe_to_dma_ctl, i / grp_num_per_ring);
        step = EpeHdrEditToDmaCtl_mc_1_dmaChanId_f - EpeHdrEditToDmaCtl_mc_0_dmaChanId_f;
        SetEpeHdrEditToDmaCtl(V, mc_0_dmaChanId_f + step * i, &epe_to_dma_ctl, i / grp_num_per_ring);
        step = EpeHdrEditToDmaCtl_uc_1_dmaChanId_f - EpeHdrEditToDmaCtl_uc_0_dmaChanId_f;
        SetEpeHdrEditToDmaCtl(V, uc_0_dmaChanId_f + step * i, &epe_to_dma_ctl, i);
    }
    cmd = DRV_IOW(EpeHdrEditToDmaCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_to_dma_ctl));

    for (i =0; i < 4; i++) /*for eunit */
    {
        step = EpeHdrEditToDmaCtl_uc_1_dmaChanId_f - EpeHdrEditToDmaCtl_uc_0_dmaChanId_f;
        SetEpeHdrEditToDmaCtl(V, uc_0_dmaChanId_f + step * i, &epe_to_dma_ctl, i);
        step = EpeHdrEditToDmaCtl_mc_1_dmaChanId_f - EpeHdrEditToDmaCtl_mc_0_dmaChanId_f;
        SetEpeHdrEditToDmaCtl(V, mc_0_dmaChanId_f + step * i, &epe_to_dma_ctl, i);
    }
    cmd = DRV_IOW(EpeHdrEditToDmaCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(SYS_PP_BASE(lchip) + 1, 0, DRV_CMD_PP_EN(cmd), &epe_to_dma_ctl));
    CTC_ERROR_RETURN(DRV_IOCTL(SYS_PP_BASE(lchip) + 2, 0, DRV_CMD_PP_EN(cmd), &epe_to_dma_ctl));

    if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
    {
        uint8 _dual_core_lchip = 0;
        SYS_VCHIP_DUAL_CORE_LCHIP_MAP(SYS_PP_BASE(lchip), _dual_core_lchip);
        CTC_ERROR_RETURN(DRV_IOCTL(_dual_core_lchip + 1, 0, DRV_CMD_PP_EN(cmd), &epe_to_dma_ctl));
        CTC_ERROR_RETURN(DRV_IOCTL(_dual_core_lchip + 2, 0, DRV_CMD_PP_EN(cmd), &epe_to_dma_ctl));
    }

    step = DmaRxStallMap_g_1_queGrpVec_f - DmaRxStallMap_g_0_queGrpVec_f;
    grp_num_per_ring = group_num / chan_num;
    for (i = 0; i < chan_num; i++)
    {
        group_vec = 0;
        for (j = 0; j < grp_num_per_ring; j++)
        {
            CTC_BIT_SET(group_vec, grp_num_per_ring * i + j);
        }
        SetDmaRxStallMap(V, g_0_queGrpVec_f + step * i, &dma_rx_map, group_vec);
    }
    cmd = DRV_IOW(DmaRxStallMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &dma_rx_map));

    /*set flowctl cos remap*/
    step = DsQMgrFlowCtlMap0_cos_1_sel_f - DsQMgrFlowCtlMap0_cos_0_sel_f;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_QOS_QUE_GRP_NODE_NUM); i++)
    {
        SetDsQMgrFlowCtlMap0(V, cos_0_sel_f + step * i, &fc_map, i);
    }
    for (i = 0; i < MCHIP_CAP(SYS_CAP_PER_DP_PHY_CHANNEL_NUM); i++)
    {
        cmd = DRV_IOW(DsQMgrFlowCtlMap0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, i, cmd, &fc_map));
        cmd = DRV_IOW(DsQMgrFlowCtlMap1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, i, cmd, &fc_map));
    }

    /*total 4 dma uc group, group 2&3 for c2c pkt*/
    sal_memset(&map_xlate, 0, sizeof(map_xlate));
    step =  DsUcDestMapXlate_g_1_xlateId_f - DsUcDestMapXlate_g_0_xlateId_f;
    for (i = 0; i < SYS_USW_MAX_CPU_REASON_GROUP_NUM_UC; i++)
    {
        SetDsUcDestMapXlate(V, g_0_xlateId_f + step * i, &map_xlate, i%SYS_USW_MAX_CPU_REASON_GROUP_NUM_UC);
    }
    SetDsUcDestMapXlate(V, defaultXlateId_f, &map_xlate, (SYS_USW_MAX_CPU_REASON_GROUP_NUM_UC*MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM))/16);
    cmd = DRV_IOW(DsUcDestMapXlate_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &map_xlate));
    return CTC_E_NONE;
}

/*
    NET_UC !DUAL_CORE_MODE               NET_UC DUAL_CORE_MODE
    +------------+------------+          +------------+------------+------------+------------+
    |  DP0_INS0  |  DP1_INS0  |          |  DP0_INS0  |  DP0_INS1  |  DP1_INS0  |  DP1_INS1  |
    |  0-311     |  312-623   |          |  0-311     |  312-623   |  624-935   |  936-1247  |
    +------------+------------+          +------------+------------+------------+------------+

    NET_MC !DUAL_CORE_MODE               NET_MC DUAL_CORE_MODE
    +-------------+                      +-------------+--------------+
    |  CURR_CORE  |                      |  CURR_CORE  |  CROSS_CORE  |
    |  0-1247     |                      |  0-1247     |  1248-2495   |
    +-------------+                      +-------------+--------------+

    DMA_UC !DUAL_CORE_MODE               DMA_UC DUAL_CORE_MODE
    +------------+                       +------------+------------+
    |  DP0_INS0  |                       |  DP0_INS0  |  DP0_INS1  |
    |  0-31      |                       |  0-31      |  32-63     |
    +------------+                       +------------+------------+

    DMA_MC !DUAL_CORE_MODE DUAL_CORE_MODE
    +-------------+
    |  CURR_CORE  |
    |  0-127      |
    +-------------+
*/
STATIC void
_sys_at_queue_stats_get_stats_param(uint8 lchip, sys_queue_node_t* p_queue_node, uint8 is_cross_core, uint8 query_ofst, sys_stats_param_t* p_st)
{

    if (SYS_QUEUE_TYPE_EXCP == p_queue_node->type)
    {
        p_st->ptr = p_queue_node->offset;
        p_st->type = SYS_STATS_TYPE_DMA_MC;
    }
    else if (SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type)
    {
        p_st->ptr = p_queue_node->offset + is_cross_core * MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM_UC);
        p_st->type = SYS_STATS_TYPE_DMA;
    }
    else if (SYS_QUE_OFST_MC == p_queue_node->node[query_ofst].type)
    {
        p_st->ptr = SYS_AT_QOS_ENCOD_CORE_QUE_MC(p_queue_node->sub_chan, (lchip - SYS_PP_BASE(lchip)), p_queue_node->dp_id, p_queue_node->node[query_ofst].ofst)
                  + (is_cross_core * SYS_CORE_PP_NUM(lchip) * MCHIP_CAP(SYS_CAP_DP_MAX_NUM) * MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) *  SYS_AT_MC_QUEUE_NUM);
        p_st->type = SYS_STATS_TYPE_QUEUE_MC;
    }
    else
    {
        p_st->ptr = SYS_AT_QOS_ENCOD_DP_QUE_UC(p_queue_node->sub_chan, p_queue_node->node[query_ofst].ofst) /* curr core */
                  + (p_queue_node->dp_id * MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) * SYS_AT_UC_QUEUE_NUM * (SYS_VCHIP_DUAL_CORE_MODE(lchip) ? 2 : 1)) /* dp */
                  + (is_cross_core * MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) * SYS_AT_UC_QUEUE_NUM);                         /* cross core */
        p_st->type = SYS_STATS_TYPE_QUEUE;
    }

    return;
}

/**
 @brief set priority color map to queue select and drop_precedence.
*/
int32
_sys_at_set_priority_queue_map(uint8 lchip, ctc_qos_pri_map_t* p_queue_pri_map)
{
    uint32 index = 0;
    uint32 cmd = 0;
    uint8 step = 0;
    ds_t ds;

    CTC_MAX_VALUE_CHECK(p_queue_pri_map->priority, SYS_QOS_QUEUE_ENQ_PRIORITY_MAX);
    CTC_VALUE_RANGE_CHECK(p_queue_pri_map->color, SYS_QOS_QUEUE_ENQ_COLOR_MIN, SYS_QOS_QUEUE_ENQ_COLOR_MAX);
    CTC_MAX_VALUE_CHECK(p_queue_pri_map->queue_select, SYS_QOS_QUEUE_ENQ_QUEUE_SELECT_MAX);
    CTC_MAX_VALUE_CHECK(p_queue_pri_map->drop_precedence, SYS_QOS_QUEUE_ENQ_ROP_PRECEDENCE_MAX);
    CTC_MAX_VALUE_CHECK(p_queue_pri_map->rep_queue_select, SYS_AT_QUEUE_ENQ_REP_QUEUE_SELECT_MAX);

    if (p_queue_pri_map->non_uc)
    {
        for (index = 0; index < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); index++)
        {
            if (SYS_IS_DMA_CHANNEL(index))
            {
                continue;
            }
            cmd = DRV_IOR(DsResrcMgmtTxPrioMapMc_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
            step = DsResrcMgmtTxPrioMapMc_g0_1_mappedTc_f - DsResrcMgmtTxPrioMapMc_g0_0_mappedTc_f;
            SetDsResrcMgmtTxPrioMapMc(V, g0_0_mappedTc_f + p_queue_pri_map->priority*step, &ds, p_queue_pri_map->queue_select);
            step = DsResrcMgmtTxPrioMapMc_g1_1_dropPrecedence_f - DsResrcMgmtTxPrioMapMc_g1_0_dropPrecedence_f;
            SetDsResrcMgmtTxPrioMapMc(V, g1_0_dropPrecedence_f + p_queue_pri_map->color*step, &ds, p_queue_pri_map->drop_precedence);
            cmd = DRV_IOW(DsResrcMgmtTxPrioMapMc_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
        }
    }
    else
    {
        for (index = 0; index < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); index++)
        {
            cmd = DRV_IOR(DsResrcMgmtTxPrioMapUc_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
            step = DsResrcMgmtTxPrioMapUc_g0_1_mappedTc_f - DsResrcMgmtTxPrioMapUc_g0_0_mappedTc_f;
            SetDsResrcMgmtTxPrioMapUc(V, g0_0_mappedTc_f + p_queue_pri_map->priority*step, &ds, p_queue_pri_map->queue_select);
            step = DsResrcMgmtTxPrioMapUc_g1_1_dropPrecedence_f - DsResrcMgmtTxPrioMapUc_g1_0_dropPrecedence_f;
            SetDsResrcMgmtTxPrioMapUc(V, g1_0_dropPrecedence_f + p_queue_pri_map->color*step, &ds, p_queue_pri_map->drop_precedence);
            cmd = DRV_IOW(DsResrcMgmtTxPrioMapUc_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
        }
    }

    index = p_queue_pri_map->priority;
    step = ResrcMgmtTxPrioMapMc_g0_1_mappedTc_f - ResrcMgmtTxPrioMapMc_g0_0_mappedTc_f;
    cmd = DRV_IOR(ResrcMgmtTxPrioMapMc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetResrcMgmtTxPrioMapMc(V, g0_0_mappedTc_f + step * index , &ds, p_queue_pri_map->rep_queue_select); 
    cmd = DRV_IOW(ResrcMgmtTxPrioMapMc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    return CTC_E_NONE;
}

/**
 @brief set priority color map to queue select and drop_precedence.
*/
int32
_sys_at_get_priority_queue_map(uint8 lchip, ctc_qos_pri_map_t* p_queue_pri_map)
{
    uint32 cmd = 0;
    uint8 step = 0;
    ds_t ds;

    CTC_MAX_VALUE_CHECK(p_queue_pri_map->priority, SYS_QOS_QUEUE_ENQ_PRIORITY_MAX);
    CTC_VALUE_RANGE_CHECK(p_queue_pri_map->color, SYS_QOS_QUEUE_ENQ_COLOR_MIN, SYS_QOS_QUEUE_ENQ_COLOR_MAX);
    
    if(p_queue_pri_map->non_uc)
    {
        cmd = DRV_IOR(DsResrcMgmtTxPrioMapMc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        step = DsResrcMgmtTxPrioMapMc_g0_1_mappedTc_f - DsResrcMgmtTxPrioMapMc_g0_0_mappedTc_f;
        p_queue_pri_map->queue_select = GetDsResrcMgmtTxPrioMapMc(V, g0_0_mappedTc_f + p_queue_pri_map->priority*step, &ds);
        step = DsResrcMgmtTxPrioMapMc_g1_1_dropPrecedence_f - DsResrcMgmtTxPrioMapMc_g1_0_dropPrecedence_f;
        p_queue_pri_map->drop_precedence = GetDsResrcMgmtTxPrioMapMc(V, g1_0_dropPrecedence_f + p_queue_pri_map->color*step, &ds);
    }
    else
    {
        cmd = DRV_IOR(DsResrcMgmtTxPrioMapUc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        step = DsResrcMgmtTxPrioMapUc_g0_1_mappedTc_f - DsResrcMgmtTxPrioMapUc_g0_0_mappedTc_f;
        p_queue_pri_map->queue_select = GetDsResrcMgmtTxPrioMapUc(V, g0_0_mappedTc_f + p_queue_pri_map->priority*step, &ds);
        step = DsResrcMgmtTxPrioMapUc_g1_1_dropPrecedence_f - DsResrcMgmtTxPrioMapUc_g1_0_dropPrecedence_f;
        p_queue_pri_map->drop_precedence = GetDsResrcMgmtTxPrioMapUc(V, g1_0_dropPrecedence_f + p_queue_pri_map->color*step, &ds);
    }

    step = ResrcMgmtTxPrioMapMc_g0_1_mappedTc_f - ResrcMgmtTxPrioMapMc_g0_0_mappedTc_f;
    cmd = DRV_IOR(ResrcMgmtTxPrioMapMc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    p_queue_pri_map->rep_queue_select = GetResrcMgmtTxPrioMapMc(V, g0_0_mappedTc_f + step * p_queue_pri_map->priority , &ds);

    return CTC_E_NONE;
}

#define _____SYS_AT_ENQ_API_____

int32
sys_at_queue_dump_port_queue_info(uint8 lchip, uint32 gport)
{
    uint32 cmd = 0;
    uint32 queue_depth = 0;
    uint32 entry_num_uc = DRV_TABLE_MAX_INDEX(lchip, DsErmQueueCntUc_t) / 2;
    uint32 entry_num_mc = DRV_TABLE_MAX_INDEX(lchip, DsErmQueueCntMc_t) / 2;
    uint32 index = 0;
    uint16 queue_id = 0;
    uint8 queue_index = 0;
    ds_t ds;
    ctc_qos_queue_id_t queue;
    sys_port_info_t port_info;
    sys_queue_node_t* p_queue_node = NULL;
    uint8 ofst = 0;
    char* str_sch[] = {"SP", "WDRR"};
    sal_memset(&port_info, 0, sizeof(sys_port_info_t));
    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, CTC_MAP_GPORT_TO_LPORT(gport), CTC_MAP_GPORT_TO_MCHAN_IDX(gport), &port_info));
    if (port_info.sub_chan_id == SYS_COMMON_USELESS_CHANNEL)
    {
        return CTC_E_INVALID_PORT;
    }

    SYS_QOS_LCHIP_CONVERT(lchip, port_info.pp_id);

    queue.queue_type = CTC_QUEUE_TYPE_NETWORK_EGRESS;
    queue.gport = gport;
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "|-pp_id:%d, dp_id:%d, chan_id:%d sub_chan_id:%d\n",
                                                   port_info.pp_id, port_info.dp_id, port_info.chan_id, port_info.sub_chan_id);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "|\n");
    for (queue_index = 0; queue_index < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); queue_index++)
    {
        queue.queue_id = queue_index;
        CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip, &queue, &queue_id));
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
        if (NULL == p_queue_node)
        {
            continue;
        }
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "|--queue-id:%d, class_prio:%d, sched_mode:%s\n",
                                                        queue_id, p_queue_node->class_prio, str_sch[p_queue_node->sched_mode]);
        for (ofst = 0; ofst < SYS_QUEUE_SUB_NODE_NUM; ofst++)
        {
            if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
            {
                index = SYS_AT_QOS_ENCOD_DP_QUE_UC(port_info.sub_chan_id, p_queue_node->node[ofst].ofst);
                cmd = DRV_IOR(DsErmQueueCntUc_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_DP_EN(cmd, port_info.dp_id), &ds));
                queue_depth = GetDsErmQueueCntUc(V, queueCnt_f, &ds);
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "|  |--node%d:UC, inst0 queue-offset:%d, queue_depth:%d\n", ofst, p_queue_node->node[ofst].ofst, queue_depth);
                if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
                {
                    uint8 _dual_core_lchip = 0;
                    SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip, _dual_core_lchip);
                    cmd = DRV_IOR(DsErmQueueCntUc_t, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(_dual_core_lchip, entry_num_uc + index, DRV_CMD_DP_EN(cmd, port_info.dp_id), &ds));
                    queue_depth = GetDsErmQueueCntUc(V, queueCnt_f, &ds);
                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "|  |--node%d:UC, inst1 queue-offset:%d, queue_depth:%d\n", ofst, p_queue_node->node[ofst].ofst, queue_depth);
                }
            }
            else if (SYS_QUE_OFST_MC == p_queue_node->node[ofst].type)
            {
                index = SYS_AT_QOS_ENCOD_CORE_QUE_MC(port_info.sub_chan_id, port_info.pp_id, port_info.dp_id, p_queue_node->node[ofst].ofst);
                cmd = DRV_IOR(DsErmQueueCntMc_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &ds));
                queue_depth = GetDsErmQueueCntMc(V, g_0_queueCnt_f, &ds);
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "|  |--node%d:MC, inst0 queue-offset:%d, queue_depth:%d\n", ofst, p_queue_node->node[ofst].ofst, queue_depth);
                if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
                {
                    uint8 _dual_core_lchip = 0;
                    SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip, _dual_core_lchip);
                    index = SYS_AT_QOS_ENCOD_CORE_QUE_MC(port_info.sub_chan_id, port_info.pp_id, port_info.dp_id, p_queue_node->node[ofst].ofst);
                    cmd = DRV_IOR(DsErmQueueCntMc_t, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(_dual_core_lchip, entry_num_mc + index, DRV_CMD_PP_EN(cmd), &ds));
                    queue_depth = GetDsErmQueueCntMc(V, g_0_queueCnt_f, &ds);
                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "|  |--node%d:MC, inst1 queue-offset:%d, queue_depth:%d\n", ofst, p_queue_node->node[ofst].ofst, queue_depth);
                }
            }
        }

        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "|\n");
    }
    return CTC_E_NONE;
}


int32
sys_at_queue_get_channel_by_queue_id(uint8 lchip, uint16 queue_id, uint16 *channel)
{
    sys_queue_node_t* p_queue_node = NULL;

    CTC_PTR_VALID_CHECK(channel);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node)
    {
        return CTC_E_NOT_EXIST;
    }
    if (SYS_QUEUE_TYPE_EUNIT == p_queue_node->type)
    {
        /*to ecpu*/
        *channel = MCHIP_CAP(SYS_CAP_CHANID_EUNIT0) + p_queue_node->offset / MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT);
    }
    else if (SYS_QUEUE_TYPE_EXCP == p_queue_node->type || SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type)
    {
        *channel = MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0);
    }
    else
    {
        SYS_QOS_LCHIP_CONVERT(lchip, p_queue_node->pp_id);
        CTC_ERROR_RETURN(sys_at_get_channel_by_sub_channel(lchip, p_queue_node->dp_id, p_queue_node->sub_chan, channel));
    }

    return CTC_E_NONE;
}

int32
sys_at_queue_get_queue_base(uint8 lchip, uint8 channel, uint16 queue_offset, uint16* queue_base)
{
    uint16 que_base = 0;
    uint16 sub_chan = 0;

    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    que_base = SYS_AT_QOS_ENCOD_QBASE(SYS_DP_CHAN_BY_SUB_CHAN(sub_chan), SYS_PP_BY_SUB_CHAN(sub_chan), SYS_DP_BY_SUB_CHAN(sub_chan));
    *queue_base = que_base + queue_offset;

    return CTC_E_NONE;
}

int32
sys_at_qos_queue_dump_status(uint8 lchip)
{
    char str[16] = {0};
    uint16 lport = 0;
    uint16 queue_base = 0;
    uint8 pp_id = 0;
    uint8 dp_id = 0;
    uint8 is_network = 1;
    sys_port_info_t port_info;

    sal_memset(&port_info, 0, sizeof(sys_port_info_t));
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "---------------------Queue allocation---------------------\n");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: %d\n", "Queue number per port", p_usw_queue_master[lchip]->queue_num_per_chanel);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "----------------------------------------------------------\n");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-15s %-10s %-10s %-10s %-8s\n", "type", "port-id", "Queue Range", "Qbase", "SubQNum");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "-----------------------------------------------------------\n");

    if (MCHIP_DMPS(lchip)->cpumac_get_lport_info_by_inner_idx)
    {
        MCHIP_DMPS(lchip)->cpumac_get_lport_info_by_inner_idx(lchip, 0, &lport, &is_network);
    }

    sal_sprintf(str, "0~%u", MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_NETWORK_MISC) - 1);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s %-10s %-11s %-10d %8d\n", "basic", "-", str,
                          MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_NORMAL), MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_GRP));

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        for (dp_id = 0; dp_id < MCHIP_CAP(SYS_CAP_DP_MAX_NUM); dp_id++)
        {
            CTC_ERROR_RETURN(_sys_at_qos_queue_get_lport_by_sub_chan(lchip, pp_id, dp_id, SYS_LOOP_SUB_CHAN, &lport));
            if (!lport)
            {
                continue;
            }
            queue_base = SYS_AT_QOS_ENCOD_QBASE(SYS_LOOP_SUB_CHAN, pp_id, dp_id);
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-7s#pp%d-dp%d %-10d %-11s %-10d %8d\n", "loop", pp_id, dp_id, lport, "-", queue_base, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN));
        }
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, SYS_RSV_PORT_OAM_CPU_ID, 0, &port_info));
    queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info.sub_chan_id, port_info.pp_id, port_info.dp_id);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s %-10d %-11s %-10d %8d\n", "Rx OAM", SYS_RSV_PORT_OAM_CPU_ID, "-", queue_base, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN));

    sal_sprintf(str, "%u~%u", MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP), MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM) - 1);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s %-10s %-11s %-10d %8d\n", "Local CPU(mc)", "-", str,
                          MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP), 8);
    sal_sprintf(str, "%u~%u", MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM),
                              MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM)
                              + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM_UC) - 1);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s %-10s %-11s %-10d %8d\n", "Local CPU(uc)", "-", str,
                          MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP), 8);

    sal_sprintf(str, "%u~%u", MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT), MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT) + (MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_NUM_EUNIT) * MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT)) - 1);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s %-10s %-11s %-10d %8d\n", "eunit", "-", str,
                          MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT), 16);

    /* CPUMac Queue*/
    if (!is_network)
    {
        for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
        {
            if ((pp_id % PP_NUM_PER_CORE) > 1)
            {
                /*only pp0/1 dp1 channel 24 support cpumac*/
                continue;
            }

            CTC_ERROR_RETURN(_sys_at_qos_queue_get_lport_by_sub_chan(lchip, pp_id, 1, SYS_DMA_SUB_CHAN, &lport));
            if (!lport)
            {
                continue;
            }
            queue_base = SYS_AT_QOS_ENCOD_QBASE(SYS_DMA_SUB_CHAN, pp_id, 1);
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-15s %-10s %-11s %-10d %8d\n", "Local CPU(ETH)", "-", "-", queue_base, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN));
        }
    }

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "\n");

    return CTC_E_NONE;
}

/*
 get queue id by queue type

*/
int32
sys_at_queue_get_queue_id(uint8 lchip, ctc_qos_queue_id_t* p_queue, uint16* queue_id)
{
    uint16 queue_base = 0;
    uint16 sub_chan = 0;
    uint16 sub_queue_id_tmp = 0;
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    switch (p_queue->queue_type)
    {
    case CTC_QUEUE_TYPE_NETWORK_EGRESS:
    case CTC_QUEUE_TYPE_INTERNAL_PORT:
    {
        sys_port_info_t port_info;

        CTC_MAX_VALUE_CHECK(p_queue->queue_id, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) - 1);
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, CTC_MAP_GPORT_TO_LPORT(p_queue->gport), CTC_MAP_GPORT_TO_MCHAN_IDX(p_queue->gport), &port_info));
        if (port_info.sub_chan_id == SYS_COMMON_USELESS_CHANNEL)
        {
            return CTC_E_INVALID_PORT;
        }
        queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info.sub_chan_id, port_info.pp_id, port_info.dp_id);
        *queue_id = queue_base + p_queue->queue_id;
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "pp_id:%d, dp_id%d, sub_channel:%d, queue_id:%d\n",
                                                     port_info.pp_id, port_info.dp_id, port_info.sub_chan_id, *queue_id);
    }
    break;
    case CTC_QUEUE_TYPE_EXCP_CPU:
    {
        sys_cpu_reason_t  *p_cpu_reason;

        if(SYS_MAP_CTC_GPORT_TO_PORT_TYPE(p_queue->gport) == CTC_GPORT_TYPE_DMA)
        {
            CTC_MAX_VALUE_CHECK(p_queue->queue_id, MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM));
            *queue_id = MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + p_queue->queue_id;
            return CTC_E_NONE;
        }

        if (p_queue->cpu_reason >= CTC_PKT_CPU_REASON_MAX_COUNT)
        {
            return CTC_E_INVALID_PARAM;
        }

        p_cpu_reason = &p_usw_queue_master[lchip]->cpu_reason[p_queue->cpu_reason];
        sub_queue_id_tmp = p_cpu_reason->sub_queue_id & 0x1ff;
        if ((sub_queue_id_tmp & 0xff) == 0xff)
        {
            return CTC_E_NOT_READY;
        }
        if (p_queue->cpu_reason == CTC_PKT_CPU_REASON_C2C_PKT)
        {
            /*queue_id: 0-15 for uc, 16-31 for mc*/
            CTC_MAX_VALUE_CHECK(p_queue->queue_id, MCHIP_CAP(SYS_CAP_QOS_REASON_C2C_MAX_QUEUE_NUM) * 2 - 1);
        }
        else if (CTC_IS_BIT_SET(p_cpu_reason->sub_queue_id, SYS_REASON_PRI_ENQ_SHIFT))
        {
            CTC_MAX_VALUE_CHECK(p_queue->queue_id, MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) - 1);
        }
        else
        {
            CTC_MAX_VALUE_CHECK(p_queue->queue_id, 0);
        }

        if (p_cpu_reason->dest_type == CTC_PKT_CPU_REASON_TO_LOCAL_CPU)
        {
            if(sub_queue_id_tmp >= MCHIP_CAP(SYS_CAP_CPU_REASON_DEST_ID_BASE_EUNIT))
            {
                CTC_MAX_VALUE_CHECK(p_queue->queue_id, MCHIP_CAP(SYS_CAP_CPU_REASON_SUB_Q_NUM_EUNIT) - 1);
                *queue_id = MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT) + (sub_queue_id_tmp&0xff) + p_queue->queue_id;
            }
            else if (p_queue->cpu_reason == CTC_PKT_CPU_REASON_C2C_PKT)
            {
                if(p_queue->queue_id >= MCHIP_CAP(SYS_CAP_QOS_REASON_C2C_MAX_QUEUE_NUM))/*mc*/
                {
                    queue_base = MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + (sub_queue_id_tmp&0xff);
                }
                else /*uc*/
                {
                    /*total 4 dma uc group, group 2&3 for c2c pkt*/
                    queue_base = MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM) + SYS_USW_MAX_CPU_REASON_GROUP_NUM_UC*MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
                }
                *queue_id = queue_base + (p_queue->queue_id&0xF);
            }
            else
            {
                *queue_id = MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + (sub_queue_id_tmp&0xff) + p_queue->queue_id;
                *queue_id += (p_cpu_reason->is_uc ? MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM) : 0);
            }
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "queue_id:%d\n", *queue_id);
        }
        else if (p_cpu_reason->dest_type == CTC_PKT_CPU_REASON_TO_LOCAL_CPU_ETH)
        {
            uint16 cpu_eth_chan_id = 0;
            uint16 cpu_channel[SYS_USW_CPU_MAC_NUM] = {MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC0), MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC1),
                                                       MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC2), MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC3)};

            cpu_eth_chan_id = cpu_channel[p_cpu_reason->dest_port & 0x3];
            CTC_ERROR_RETURN(sys_at_queue_get_queue_base(lchip, cpu_eth_chan_id, p_queue->queue_id, queue_id))
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "channel:%d, queue_id:%d\n", sub_chan, *queue_id);
        }
        else
        {
            /*TBD*/
            return CTC_E_INVALID_PARAM;
        }
    }
    break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_at_queue_get_queue_offset(uint8 lchip, ctc_qos_queue_id_t* p_queue, uint8* queue_offset)
{
    uint16 queue_id = 0;
    sys_queue_node_t  *p_queue_node = NULL;

    CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip, p_queue, &queue_id));

    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node || (SYS_QUE_OFST_NONE == p_queue_node->node[0].type && SYS_QUE_OFST_NONE == p_queue_node->node[1].type))
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    *queue_offset = p_queue_node->node[SYS_AT_COS_SUB_NODE_OFST(p_queue_node, p_queue->class_prio)].ofst;

    return CTC_E_NONE;
}

int32
sys_at_queue_stats_query(uint8 lchip, ctc_qos_queue_stats_t* p_stats_param)
{
    ctc_stats_basic_t stats_uc;
    ctc_stats_basic_t stats_mc;
    ctc_stats_basic_t stats_uc_tmp;
    ctc_stats_basic_t stats_mc_tmp;
    ctc_qos_queue_stats_info_t* p_stats = NULL;
    sys_stats_param_t st_param;
    uint16 queue_id = 0;
    uint8 pp_id = 0;
    uint8 pp_id_usr = 0;
    uint8 lchip_tmp = 0;
    uint8 is_cross_core = 0;
    sys_queue_node_t *p_queue_node = NULL;
    uint8 ofst = 0;
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_MAX_VALUE_CHECK(p_stats_param->queue.class_prio, SYS_QUEUE_SUB_NODE_NUM-1);

    sal_memset(&stats_uc, 0, sizeof(stats_uc));
    sal_memset(&stats_mc, 0, sizeof(stats_mc));
    sal_memset(&stats_uc_tmp, 0, sizeof(stats_uc_tmp));
    sal_memset(&stats_mc_tmp, 0, sizeof(stats_mc_tmp));
    sal_memset(&st_param, 0, sizeof(st_param));
    st_param.num = 1;
    CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip,
                                                       &p_stats_param->queue,
                                                       &queue_id));

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Queue id = %d\n", queue_id);

    p_stats = &p_stats_param->stats;
    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    pp_id = p_queue_node->pp_id;
    CTC_MAX_VALUE_CHECK(pp_id, (SYS_PP_NUM(lchip)-1));
    CTC_BMP_FIRST_VALID(&p_stats_param->pp_bmp, SYS_PP_NUM(lchip), pp_id_usr);
    CTC_MAX_VALUE_CHECK(pp_id_usr, (SYS_PP_NUM(lchip)-1));
    is_cross_core = (p_stats_param->pp_bmp && (sys_usw_vchip_get_core_pp_base(pp_id) != sys_usw_vchip_get_core_pp_base(pp_id_usr)));
    if (is_cross_core && !SYS_VCHIP_DUAL_CORE_MODE(lchip))
    {
        return CTC_E_NONE;
    }
    else if (is_cross_core)
    {
        /* convert pp_id to dual core pp_id */
        pp_id = (pp_id + SYS_CORE_PP_NUM(lchip)) % SYS_PP_NUM(lchip);
    }

    ofst = SYS_AT_COS_SUB_NODE_OFST(p_queue_node, p_stats_param->queue.class_prio);
    if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
    {
        lchip_tmp = lchip;
        SYS_QOS_LCHIP_CONVERT(lchip_tmp, pp_id);
        _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, is_cross_core, ofst, &st_param);
        CTC_ERROR_RETURN(sys_usw_flow_stats_get_stats(lchip_tmp, &st_param, &stats_uc));
        if ((0 == p_stats_param->pp_bmp) && SYS_VCHIP_DUAL_CORE_MODE(lchip))
        {
            uint8 _dual_core_lchip = 0;
            SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip_tmp, _dual_core_lchip);
            _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, 1, ofst, &st_param);
            CTC_ERROR_RETURN(sys_usw_flow_stats_get_stats(_dual_core_lchip, &st_param, &stats_uc_tmp));
            stats_uc.packet_count += stats_uc_tmp.packet_count;
            stats_uc.byte_count += stats_uc_tmp.byte_count;
        }
    }
    else if (SYS_QUE_OFST_MC == p_queue_node->node[ofst].type)
    {
        uint8 pp_id_tmp = pp_id;
        uint8 loop_end = pp_id_tmp + 1;
        if (!(SYS_QUEUE_TYPE_EXCP == p_queue_node->type || SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type))
        {
            pp_id_tmp = pp_id_tmp / SYS_CORE_PP_NUM(lchip) * SYS_CORE_PP_NUM(lchip); /*pp_id to base*/
            loop_end = pp_id_tmp + SYS_CORE_PP_NUM(lchip);
        }
        for (; pp_id_tmp < loop_end; pp_id_tmp++)
        {
            lchip_tmp = lchip;
            SYS_QOS_LCHIP_CONVERT(lchip_tmp, pp_id_tmp);
            _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, is_cross_core, ofst, &st_param);
            CTC_ERROR_RETURN(sys_usw_flow_stats_get_stats(lchip_tmp, &st_param, &stats_mc_tmp));
            stats_mc.packet_count += stats_mc_tmp.packet_count;
            stats_mc.byte_count += stats_mc_tmp.byte_count;
            if ((0 == p_stats_param->pp_bmp) && SYS_VCHIP_DUAL_CORE_MODE(lchip))
            {
                uint8 _dual_core_lchip = 0;
                SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip_tmp, _dual_core_lchip);
                _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, 1, ofst, &st_param);
                CTC_ERROR_RETURN(sys_usw_flow_stats_get_stats(_dual_core_lchip, &st_param, &stats_mc_tmp));
                stats_mc.packet_count += stats_mc_tmp.packet_count;
                stats_mc.byte_count += stats_mc_tmp.byte_count;
            }
        }
    }
    p_stats->drop_packets = stats_uc.packet_count + stats_mc.packet_count;
    p_stats->deq_packets = stats_uc.byte_count + stats_mc.byte_count;
    return CTC_E_NONE;
}

int32
sys_at_queue_stats_clear(uint8 lchip, ctc_qos_queue_stats_t* p_stats_param)
{
    uint16 queue_id = 0;
    uint8 pp_id = 0;
    uint8 pp_id_usr = 0;
    uint8 is_cross_core = 0;
    uint8 lchip_tmp = 0;
    sys_stats_param_t st_param;
    sys_queue_node_t *p_queue_node = NULL;
    uint8 ofst = 0;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_MAX_VALUE_CHECK(p_stats_param->queue.class_prio, SYS_QUEUE_SUB_NODE_NUM-1);

    sal_memset(&st_param, 0, sizeof(st_param));
    st_param.num = 1;
    CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip, &p_stats_param->queue,
                                                       &queue_id));

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Queue id = %d\n", queue_id);
    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    pp_id = p_queue_node->pp_id;
    CTC_MAX_VALUE_CHECK(pp_id, (SYS_PP_NUM(lchip)-1));
    CTC_BMP_FIRST_VALID(&p_stats_param->pp_bmp, SYS_PP_NUM(lchip), pp_id_usr);
    CTC_MAX_VALUE_CHECK(pp_id_usr, (SYS_PP_NUM(lchip)-1));

    /* is_cross_core: core 0 queue get core 1 stats, core 1 queue get core 0 stats */
    is_cross_core = (p_stats_param->pp_bmp && (sys_usw_vchip_get_core_pp_base(pp_id) != sys_usw_vchip_get_core_pp_base(pp_id_usr)));
    if (is_cross_core && !SYS_VCHIP_DUAL_CORE_MODE(lchip))
    {
        return CTC_E_NONE;
    }
    else if (is_cross_core)
    {
        /* convert pp_id to dual core pp_id */
        pp_id = (pp_id + PP_NUM_PER_CORE) % SYS_PP_NUM(lchip);
    }

    ofst = SYS_AT_COS_SUB_NODE_OFST(p_queue_node, p_stats_param->queue.class_prio);
    if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
    {
        lchip_tmp = lchip;
        SYS_QOS_LCHIP_CONVERT(lchip_tmp, pp_id);
        _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, is_cross_core, ofst, &st_param);
        CTC_ERROR_RETURN(sys_usw_flow_stats_clear_stats(lchip_tmp, &st_param));
        /* pp_bmp != 0: only get 1 core stats, pp_bmp == 0: get 2 core stats */
        if ((0 == p_stats_param->pp_bmp) && SYS_VCHIP_DUAL_CORE_MODE(lchip))
        {
            uint8 _dual_core_lchip = 0;
            SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip_tmp, _dual_core_lchip);
            _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, 1, ofst, &st_param);
            CTC_ERROR_RETURN(sys_usw_flow_stats_clear_stats(_dual_core_lchip, &st_param));
        }
    }
    else if (SYS_QUE_OFST_MC == p_queue_node->node[ofst].type)
    {
        uint8 pp_id_tmp = pp_id;
        uint8 loop_end = pp_id_tmp + 1;
        if (!(SYS_QUEUE_TYPE_EXCP == p_queue_node->type || SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type))
        {
            pp_id_tmp = pp_id_tmp / PP_NUM_PER_CORE * PP_NUM_PER_CORE; /*pp_id to base*/
            loop_end = pp_id_tmp + PP_NUM_PER_CORE;
        }
        for (; pp_id_tmp < loop_end; pp_id_tmp++)
        {
            lchip_tmp = lchip;
            SYS_QOS_LCHIP_CONVERT(lchip_tmp, pp_id_tmp);
            _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, 0, ofst, &st_param);
            CTC_ERROR_RETURN(sys_usw_flow_stats_clear_stats(lchip_tmp, &st_param));
            /* pp_bmp != 0: only get 1 core stats, pp_bmp == 0: get 2 core stats */
            if ((0 == p_stats_param->pp_bmp) && SYS_VCHIP_DUAL_CORE_MODE(lchip))
            {
                uint8 _dual_core_lchip = 0;
                SYS_VCHIP_DUAL_CORE_LCHIP_MAP(lchip_tmp, _dual_core_lchip);
                _sys_at_queue_stats_get_stats_param(lchip, p_queue_node, 1, ofst, &st_param);
                CTC_ERROR_RETURN(sys_usw_flow_stats_clear_stats(_dual_core_lchip, &st_param));
            }
        }
    }

    return CTC_E_NONE;
}

int32
sys_at_prio_class_stats_query(uint8 lchip, void* p_stats_param)
{
    uint32 cmd = 0;
    uint16 lport = 0;
    uint32 sub_chan_id = 0;
    DsStatsPortTcUc_m porttcuc;
    DsStatsPortTcMc_m porttcmc;
    ctc_qos_prio_class_stats_t*  p_stats = (ctc_qos_prio_class_stats_t*)p_stats_param;
    sys_port_info_t port_info = {0};

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_PTR_VALID_CHECK(p_stats);
    CTC_MAX_VALUE_CHECK(p_stats->prio_class, 7);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stats->gport, lchip, lport);
    if (!SYS_GPORT_IS_NETWORK_PORT(p_stats->gport))
    {
        return CTC_E_INVALID_PORT;
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, CTC_MAP_GPORT_TO_MCHAN_IDX(p_stats->gport), &port_info));
    sub_chan_id = port_info.sub_chan_id;
    SYS_QOS_LCHIP_CONVERT(lchip, port_info.pp_id);

    /*AT TODO:need call stats for stats sync*/
    cmd = DRV_IOR(DsStatsPortTcUc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (sub_chan_id << 3 | p_stats->prio_class), DRV_CMD_DP_EN(cmd, port_info.dp_id), &porttcuc));
    p_stats->stats.deq_packets = GetDsStatsPortTcUc(V, g_0_packetCount_f, &porttcuc);
    p_stats->stats.drop_packets = GetDsStatsPortTcUc(V, g_1_packetCount_f, &porttcuc);


    cmd = DRV_IOR(DsStatsPortTcMc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (sub_chan_id << 3 | p_stats->prio_class), DRV_CMD_DP_EN(cmd, port_info.dp_id), &porttcmc));
    p_stats->stats.deq_packets += GetDsStatsPortTcMc(V, g_0_packetCount_f, &porttcmc);
    p_stats->stats.drop_packets += GetDsStatsPortTcMc(V, g_1_packetCount_f, &porttcmc);

    return CTC_E_NONE;
}

int32
sys_at_prio_class_stats_clear(uint8 lchip, void* p_stats_param)
{
    uint32 cmd = 0;
    uint16 lport = 0;
    uint32 sub_chan_id = 0;
    uint32  dp_id = 0;
    DsStatsPortTcUc_m porttcuc;
    DsStatsPortTcMc_m porttcmc;
    ctc_qos_prio_class_stats_t*  p_stats = (ctc_qos_prio_class_stats_t*)p_stats_param;
    sys_port_info_t port_info = {0};

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_PTR_VALID_CHECK(p_stats);
    CTC_MAX_VALUE_CHECK(p_stats->prio_class, 7);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(p_stats->gport, lchip, lport);
    if (!SYS_GPORT_IS_NETWORK_PORT(p_stats->gport))
    {
        return CTC_E_INVALID_PORT;
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, CTC_MAP_GPORT_TO_MCHAN_IDX(p_stats->gport), &port_info));
    sub_chan_id = port_info.sub_chan_id;
    dp_id = port_info.dp_id;
    SYS_QOS_LCHIP_CONVERT(lchip, port_info.pp_id);

    /*AT TODO:need call stats for stats sync*/
    cmd = DRV_IOR(DsStatsPortTcUc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (sub_chan_id << 3 | p_stats->prio_class), DRV_CMD_DP_EN(cmd, dp_id), &porttcuc));
    SetDsStatsPortTcUc(V, g_0_packetCount_f, &porttcuc, 0);
    SetDsStatsPortTcUc(V, g_1_packetCount_f, &porttcuc, 0);
    cmd = DRV_IOW(DsStatsPortTcUc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (sub_chan_id << 3 | p_stats->prio_class), DRV_CMD_DP_EN(cmd, dp_id), &porttcuc));


    cmd = DRV_IOR(DsStatsPortTcMc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (sub_chan_id << 3 | p_stats->prio_class), DRV_CMD_DP_EN(cmd, dp_id), &porttcmc));
    SetDsStatsPortTcMc(V, g_0_packetCount_f, &porttcmc, 0);
    SetDsStatsPortTcMc(V, g_1_packetCount_f, &porttcmc, 0);
    cmd = DRV_IOW(DsStatsPortTcMc_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, (sub_chan_id << 3 | p_stats->prio_class), DRV_CMD_DP_EN(cmd, dp_id), &porttcmc));

    return CTC_E_NONE;
}

int32
sys_at_queue_traverse_queue_node(uint8 lchip, uint16 lport,
                                SYS_QOS_TRAVERSE_FUNC fn,
                                void* user_data)
{
    sys_queue_node_t* p_que_node = NULL;
    sys_traverse_t traverse_data;
    sys_port_info_t port_info;
    int32 ret = 0;
    uint16 que_id = 0;
    uint16 queue_base = 0;
    uint16 loop_max = MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM);
    uint8 ofst = 0;
    uint8 is_dma_q = 0;
    uint8 is_mc_q = 0;

    if (0xFFFF != lport)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, 0, &port_info));
        queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info.sub_chan_id, port_info.pp_id, port_info.dp_id);
        loop_max = MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
    }
    sal_memset(&traverse_data, 0, sizeof(sys_traverse_t));
    traverse_data.data = user_data;
    for (que_id = 0; que_id < loop_max; que_id++)
    {
        p_que_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + que_id);
        if (NULL == p_que_node)
        {
            continue;
        }
        is_dma_q = (SYS_QUEUE_TYPE_EXCP == p_que_node->type) || (SYS_QUEUE_TYPE_EXCP_UC == p_que_node->type);
        traverse_data.value1 = que_id;
        traverse_data.value2 = (p_que_node->pp_id << 20) | (p_que_node->dp_id << 16) | p_que_node->sub_chan;
        for (ofst = 0; ofst < SYS_QUEUE_SUB_NODE_NUM; ofst++)
        {
            if (SYS_QUE_OFST_NONE == p_que_node->node[ofst].type)
            {
                continue;
            }
            is_mc_q = SYS_QUE_OFST_MC == p_que_node->node[ofst].type;
            traverse_data.value3 = (is_dma_q << 31) | (is_mc_q << 30) | (ofst << 16) | (p_que_node->offset << 8) | p_que_node->node[ofst].ofst;
            traverse_data.value4 = is_dma_q ? p_que_node->offset
                                            : is_mc_q ? SYS_AT_QOS_ENCOD_CORE_QUE_MC(p_que_node->sub_chan, p_que_node->pp_id, p_que_node->dp_id, p_que_node->node[ofst].ofst)
                                                      : SYS_AT_QOS_ENCOD_DP_QUE_UC(p_que_node->sub_chan, p_que_node->node[ofst].ofst);
            ret = fn(lchip, &traverse_data);
            if (ret != CTC_E_NONE)
            {
                return ret;
            }
        }
    }
    return CTC_E_NONE;
}

int32
sys_at_queue_get_span_on_drop_mcq(uint8 lchip, sys_port_info_t* port_info, uint8* mcq)
{
    sys_queue_node_t* p_que_node = NULL;
    uint16 queue_base = 0;
    uint8 que_id = 0;
    uint8 ofst = 0;
    uint8 find = 0;

    queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info->sub_chan_id, port_info->pp_id, port_info->dp_id);
    for (que_id = 0; que_id < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); que_id++)
    {
        p_que_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + que_id);
        if (NULL == p_que_node)
        {
            continue;
        }
        for (ofst = 0; ofst < SYS_QUEUE_SUB_NODE_NUM; ofst++)
        {
            if (SYS_QUE_OFST_MC != p_que_node->node[ofst].type || !p_que_node->node[ofst].qdrop_en)
            {
                continue;
            }
            *mcq = p_que_node->node[ofst].ofst;
            find = 1;
            break;
        }
    }
    return find ? CTC_E_NONE : CTC_E_NOT_EXIST;
}

int32
sys_at_monitor_drop_stats_query(uint8 lchip, void* p_stats_param)
{
    uint32 cmd = 0;
    uint8 pp_id = 0;
    McQWriteStatsSpanOnDrop_m stats_sod;
    McQWriteSpanOnDropCtl_m sod_ctl;
    ctc_qos_stats_info_t*  p_stats = (ctc_qos_stats_info_t*)p_stats_param;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_PTR_VALID_CHECK(p_stats);

    cmd = DRV_IOR(McQWriteSpanOnDropCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sod_ctl)); 

    if (0 == GetMcQWriteSpanOnDropCtl(V, spanOnDropRandomEn_f, &sod_ctl))
    {
        return CTC_E_NONE;
    }

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        /*AT TODO:need call stats for stats sync*/
        cmd = DRV_IOR(McQWriteStatsSpanOnDrop_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(SYS_PP_BASE(lchip)+pp_id, 0, DRV_CMD_PP_EN(cmd), &stats_sod));
        p_stats->deq_packets += GetMcQWriteStatsSpanOnDrop(V, g_0_packetCount_f, &stats_sod);
        p_stats->drop_packets += GetMcQWriteStatsSpanOnDrop(V, g_1_packetCount_f, &stats_sod);
    }

    return CTC_E_NONE;
}

int32
sys_at_monitor_drop_stats_clear(uint8 lchip, void* p_stats_param)
{
    uint32 cmd = 0;
    McQWriteStatsSpanOnDrop_m stats_sod;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    /*AT TODO:need call stats for stats sync*/
    cmd = DRV_IOR(McQWriteStatsSpanOnDrop_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &stats_sod));
    SetMcQWriteStatsSpanOnDrop(V, g_0_packetCount_f, &stats_sod, 0);
    SetMcQWriteStatsSpanOnDrop(V, g_1_packetCount_f, &stats_sod, 0);
    cmd = DRV_IOW(McQWriteStatsSpanOnDrop_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &stats_sod));

    return CTC_E_NONE;
}

int32
sys_at_stats_query(uint8 lchip, ctc_qos_stats_type_t type, void* p_stats_param)
{

    switch(type)
    {
    case CTC_QOS_STATS_TYPE_PRIO_CLASS:
        CTC_ERROR_RETURN(sys_at_prio_class_stats_query(lchip, p_stats_param));
        break;
    case CTC_QOS_STATS_TYPE_DROP_MONITOR:
        CTC_ERROR_RETURN(sys_at_monitor_drop_stats_query(lchip, p_stats_param));
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_at_stats_clear(uint8 lchip, ctc_qos_stats_type_t type, void* p_stats_param)
{
    switch(type)
    {
    case CTC_QOS_STATS_TYPE_PRIO_CLASS:
        CTC_ERROR_RETURN(sys_at_prio_class_stats_clear(lchip, p_stats_param));
        break;
    case CTC_QOS_STATS_TYPE_DROP_MONITOR:
        CTC_ERROR_RETURN(sys_at_monitor_drop_stats_clear(lchip, p_stats_param));
        break;
    default:
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_at_qos_queue_get_buffer_watermark(uint8 lchip, uint8 query_pp_id, ctc_qos_queue_id_t *queue, uint32 *uc_cnt)
{
    uint16 queue_idx = 0;
    uint32 cmd = 0;
    uint32 field_value = 0;
    uint16 queue_id = 0;
    uint8  ofst = 0;
    sys_queue_node_t* p_queue_node = NULL;

    CTC_MAX_VALUE_CHECK(queue->class_prio, SYS_QUEUE_SUB_NODE_NUM-1);

    CTC_ERROR_RETURN(sys_usw_qos_queue_get_queue_id(lchip, queue, &queue_id));
    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }
    CTC_MAX_VALUE_CHECK(p_queue_node->pp_id, (SYS_PP_NUM(lchip)-1));

    ofst = SYS_AT_COS_SUB_NODE_OFST(p_queue_node, queue->class_prio);
    if (SYS_QUEUE_TYPE_NORMAL == p_queue_node->type || SYS_QUEUE_TYPE_EUNIT == p_queue_node->type)
    {
        if (SYS_QUE_OFST_UC != p_queue_node->node[ofst].type)
        {
            return CTC_E_NONE;
        }
        queue_idx = SYS_AT_QOS_ENCOD_DP_QUE_UC(p_queue_node->sub_chan, p_queue_node->node[ofst].ofst);
        CTC_ERROR_RETURN(sys_at_qos_get_corss_core_lchip(&lchip, p_queue_node->pp_id, query_pp_id));
        queue_idx += sys_at_qos_get_corss_core_tbl_idx(lchip, p_queue_node->pp_id, query_pp_id, DRV_INS(1, 0));
        cmd = DRV_IOR(DsErmQueueCntUcMax_t, DsErmQueueCntUcMax_queueCnt_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, queue_idx, DRV_CMD_DP_EN(cmd, p_queue_node->dp_id), &field_value));
    }
    else if (SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type)
    {
        queue_idx = p_queue_node->offset;
        CTC_ERROR_RETURN(sys_at_qos_get_corss_core_lchip(&lchip, p_queue_node->pp_id, query_pp_id));
        queue_idx += sys_at_qos_get_corss_core_tbl_idx(lchip, p_queue_node->pp_id, query_pp_id, DRV_INS(1, 0));
        cmd = DRV_IOR(DsErmDmaCntUcMax_t, DsErmDmaCntUcMax_queueCnt_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, queue_idx, DRV_CMD_DP_EN(cmd, p_queue_node->dp_id), &field_value));
    }
    if (uc_cnt)
    {
        *uc_cnt = field_value;
    }
    return CTC_E_NONE;
}

int32
sys_at_qos_queue_clear_buffer_watermark(uint8 lchip, uint8 query_pp_id, ctc_qos_queue_id_t *queue)
{
    uint16 queue_idx = 0;
    uint32 cmd = 0;
    uint32 field_value = 0;
    uint16 queue_id = 0;
    uint8  ofst = 0;
    sys_queue_node_t* p_queue_node = NULL;
    
    CTC_MAX_VALUE_CHECK(queue->class_prio, SYS_QUEUE_SUB_NODE_NUM-1);

    CTC_ERROR_RETURN(sys_usw_qos_queue_get_queue_id(lchip, queue, &queue_id));
    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node || (SYS_QUE_OFST_NONE == p_queue_node->node[0].type && SYS_QUE_OFST_NONE == p_queue_node->node[1].type))
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    ofst = SYS_AT_COS_SUB_NODE_OFST(p_queue_node, queue->class_prio);
    SYS_QOS_LCHIP_CONVERT(lchip, p_queue_node->pp_id);
    if (SYS_QUEUE_TYPE_NORMAL == p_queue_node->type || SYS_QUEUE_TYPE_EUNIT == p_queue_node->type)
    {
        if (SYS_QUE_OFST_UC != p_queue_node->node[ofst].type)
        {
            return CTC_E_NONE;
        }
        queue_idx = SYS_AT_QOS_ENCOD_DP_QUE_UC(p_queue_node->sub_chan, p_queue_node->node[ofst].ofst);
        CTC_ERROR_RETURN(sys_at_qos_get_corss_core_lchip(&lchip, p_queue_node->pp_id, query_pp_id));
        queue_idx += sys_at_qos_get_corss_core_tbl_idx(lchip, p_queue_node->pp_id, query_pp_id, DRV_INS(1, 0));
        cmd = DRV_IOW(DsErmQueueCntUcMax_t, DsErmQueueCntUcMax_queueCnt_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, queue_idx, DRV_CMD_DP_EN(cmd, p_queue_node->dp_id), &field_value));
    }
    else if (SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type)
    {
        queue_idx = p_queue_node->offset;
        CTC_ERROR_RETURN(sys_at_qos_get_corss_core_lchip(&lchip, p_queue_node->pp_id, query_pp_id));
        queue_idx += sys_at_qos_get_corss_core_tbl_idx(lchip, p_queue_node->pp_id, query_pp_id, DRV_INS(1, 0));
        cmd = DRV_IOW(DsErmDmaCntUcMax_t, DsErmDmaCntUcMax_queueCnt_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, queue_idx, DRV_CMD_DP_EN(cmd, p_queue_node->dp_id), &field_value));
    }
    return CTC_E_NONE;
}

typedef int32 (*sys_at_queue_map_func_cb)(uint8 lchip, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map, uint8 flag);
int32
_sys_at_qos_queue_map_set(uint8 lchip, ctc_qos_queue_map_t* que_map)
{
    sys_at_queue_map_func_cb  p_func = NULL;
    ctc_port_bitmap_t port_bmp_zero;
    sys_port_info_t port_info;
    ctc_qos_shape_t que_shape;
    int32 ret = 0;
    uint16 lport = 0;
    uint16 loop_end = 0;
    uint8  set_port = 0;
    uint8 loop = 0;
    uint8 gchip = 0;
    uint8 need_check = 1;
    uint8 index = 0;

    CTC_PTR_VALID_CHECK(que_map);

    switch (que_map->mode)
    {
        case CTC_QOS_PORT_QUEUE_FLEX_MODE:
            p_func = _sys_at_qos_queue_map_port_flex_mode;
        break;
        case CTC_QOS_PORT_QUEUE_FIXED_MODE:
            p_func = _sys_at_qos_queue_map_port_fixed_mode;
        break;
        default:
            return CTC_E_NOT_SUPPORT;
    }
    sys_usw_get_gchip_id(lchip, &gchip);
    sal_memset(&que_shape, 0, sizeof(que_shape));
    sal_memset(port_bmp_zero, 0, sizeof(ctc_port_bitmap_t));
    sal_memset(&port_info, 0, sizeof(sys_port_info_t));
    if (!sal_memcmp(que_map->port_bmp, port_bmp_zero, sizeof(ctc_port_bitmap_t)))
    {
        set_port = 1;
		lport = CTC_MAP_GPORT_TO_LPORT(que_map->gport);
		index = CTC_MAP_GPORT_TO_MCHAN_IDX(que_map->gport);
		loop_end = lport + 1;
		
    }
	else
	{
	    loop_end = MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP);
	}

    for (; lport < loop_end; lport++)
    {
        if (!set_port && !CTC_BMP_ISSET(que_map->port_bmp, lport))
        {
            continue;
        }
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, index, &port_info));
        if (SYS_DMPS_NETWORK_PORT != port_info.port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_info.port_type 
            && SYS_DMPS_CPU_MAC_PORT != port_info.port_type)
        {
            if(set_port)
            {
                return CTC_E_INVALID_GLOBAL_PORT;
            }
            continue;
        }

        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lport %d flexq maping.\n", lport);
        /*1. port drop enable */
        CTC_ERROR_RETURN(sys_at_queue_set_port_drop_en(lchip, port_info.chan_id, 1, NULL));

        /*2. flexq map */
        ret = p_func(lchip, &port_info, que_map, need_check);

        /*3. port drop disable*/
        CTC_ERROR_RETURN(sys_at_queue_set_port_drop_en(lchip, port_info.chan_id, 0, NULL));
        if (ret != CTC_E_NONE)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lport %d flexq maping error.\n", lport);
            return ret;
        }
        /*set shape default when change queue map mode*/
        que_shape.type = CTC_QOS_SHAPE_QUEUE;
        que_shape.shape.queue_shape.enable = 0;
        que_shape.shape.queue_shape.queue.queue_type = CTC_QUEUE_TYPE_NETWORK_EGRESS;
        que_shape.shape.queue_shape.queue.gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);
        for (loop = 0; loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_GRP); loop++)
        {
            que_shape.shape.queue_shape.queue.queue_id = loop;
            CTC_ERROR_RETURN(sys_at_qos_set_shape(lchip, &que_shape));
        }

        need_check = 0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_get_enq_num(uint8 lchip, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map, uint8* pos)
{
    sys_queue_node_t* p_queue_node = NULL;
    sys_queue_node_t* p_queue_node_last = NULL;
    ctc_qos_queue_enq_t* p_enq = NULL;
    uint8 cos_ofst = 0;
    uint8 ucq_num_last = 0;
    uint8 mcq_num_last = 0;
    uint8 ucq_num = 0;
    uint8 mcq_num = 0;
    uint8 ofst = 0;
    uint16 queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info->sub_chan_id, port_info->pp_id, port_info->dp_id);

    for (cos_ofst = 0; cos_ofst < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); cos_ofst++)
    {
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + cos_ofst);
        if (NULL == p_queue_node)
        {
            continue;
        }
        if (SYS_QUE_OFST_NONE == p_queue_node->node[0].type && SYS_QUE_OFST_NONE == p_queue_node->node[1].type)
        {
            continue;
        }
        for (ofst = 0; ofst < SYS_QUEUE_SUB_NODE_NUM; ofst++)
        {
            if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
            {
                ucq_num++;
            }
            else if (SYS_QUE_OFST_MC == p_queue_node->node[ofst].type)
            {
                mcq_num++;
            }
        }

        if (!p_queue_node_last
            || p_queue_node_last->sched_mode != p_queue_node->sched_mode
            || p_queue_node_last->class_prio != p_queue_node->class_prio
            /*|| (ucq_num != ucq_num_last && mcq_num != mcq_num_last)*/
            || (ucq_num != ucq_num_last && mcq_num_last)
            || (ucq_num_last && mcq_num != mcq_num_last)
            || (p_queue_node->node[0].type != SYS_QUE_OFST_NONE && p_queue_node->node[1].type != SYS_QUE_OFST_NONE))
        {
            /*new node*/
            ucq_num -= ucq_num_last;
            mcq_num -= mcq_num_last;
            p_queue_node_last = p_queue_node;
            if (que_map->enq && (que_map->enq_num > *pos))
            {
                p_enq = que_map->enq + (*pos);
                p_enq->pkt_type = 0;
                p_enq->q_base = cos_ofst;
                p_enq->ucq_num = ucq_num;
                p_enq->mcq_num = mcq_num;
                p_enq->class_prio = p_queue_node->class_prio;
                p_enq->sched_mode = p_queue_node->sched_mode;
            }
            else
            {
                p_enq = NULL;
            }

            (*pos)++;
        }
        else if (p_enq)
        {
            /*update last node*/
            p_enq->ucq_num = ucq_num;
            p_enq->mcq_num = mcq_num;
        }
        mcq_num_last = mcq_num;
        ucq_num_last = ucq_num;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_map_pkt_type_sys2ctc(uint8 type, uint8 sys_type_bmp, uint32* ctc_type_bmp)
{
    if (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_C2C))
    {
        CTC_SET_FLAG(*ctc_type_bmp, CTC_QOS_QUEUE_PKT_TYPE_C2C);
    }
    if (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_CPU_PKT))
    {
        CTC_SET_FLAG(*ctc_type_bmp, CTC_QOS_QUEUE_PKT_TYPE_CPU);
    }
    if (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_OAM))
    {
        CTC_SET_FLAG(*ctc_type_bmp, CTC_QOS_QUEUE_PKT_TYPE_OAM);
    }
    if (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_SPAN))
    {
        CTC_SET_FLAG(*ctc_type_bmp, CTC_QOS_QUEUE_PKT_TYPE_SPAN);
    }
    if (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_UC) || (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_MC) && type == SYS_QUE_OFST_MC))
    {
        CTC_SET_FLAG(*ctc_type_bmp, CTC_QOS_QUEUE_PKT_TYPE_KNOWN);
    }
    if (CTC_IS_BIT_SET(sys_type_bmp, SYS_QUE_MAP_TYPE_UNKNOWN_MC))
    {
        CTC_SET_FLAG(*ctc_type_bmp, CTC_QOS_QUEUE_PKT_TYPE_UNKNOWN);
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_encode_enq_mode(uint8 lchip, uint8 q_ofst, sys_queue_node_t* p_que_node,
                                    ctc_qos_queue_map_t* que_map, uint8* pos, uint8* qmaptype_valid)
{
    ctc_qos_queue_enq_t* p_enq = NULL;
    if (SYS_QUE_OFST_UC == p_que_node->node[q_ofst].type && qmaptype_valid[p_que_node->node[q_ofst].ofst])
    {
        if (que_map->enq && (que_map->enq_num > *pos))
        {
            p_enq = que_map->enq + (*pos);
            _sys_at_queue_map_pkt_type_sys2ctc(p_que_node->node[q_ofst].type, qmaptype_valid[p_que_node->node[q_ofst].ofst], &p_enq->pkt_type);
            p_enq->q_base = p_que_node->offset;
            p_enq->ucq_num = 1;
            p_enq->mcq_num = 0;
            p_enq->class_prio = q_ofst;
            p_enq->enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;
        }
        (*pos)++;
    }
    else if (SYS_QUE_OFST_MC == p_que_node->node[q_ofst].type
            && qmaptype_valid[MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) + p_que_node->node[q_ofst].ofst])
    {
        if (que_map->enq && (que_map->enq_num > *pos))
        {
            p_enq = que_map->enq + (*pos);
            _sys_at_queue_map_pkt_type_sys2ctc(p_que_node->node[q_ofst].type, qmaptype_valid[MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) + p_que_node->node[q_ofst].ofst], &p_enq->pkt_type);
            p_enq->q_base = p_que_node->offset;
            p_enq->ucq_num = 0;
            p_enq->mcq_num = 1;
            p_enq->class_prio = q_ofst;
            p_enq->enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;
        }
        (*pos)++;
    }
    else if (p_que_node->node[q_ofst].qdrop_en)
    {
        if (que_map->enq && (que_map->enq_num > *pos))
        {
            p_enq = que_map->enq + (*pos);
            p_enq->pkt_type = CTC_QOS_QUEUE_PKT_TYPE_QDROP;
            p_enq->q_base = p_que_node->offset;
            p_enq->ucq_num = 0;
            p_enq->mcq_num = 1;
            p_enq->class_prio = q_ofst;
            p_enq->enq_mode = CTC_QOS_ENQ_MODE_UESER_DEFINE;
        }
        (*pos)++;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_queue_map_get_enq_mode(uint8 lchip, sys_port_info_t* port_info, ctc_qos_queue_map_t* que_map, uint8* pos)
{
    sys_queue_node_t *p_que_node = NULL;
    DsMcQueueMap_m mcq_map;
    DsUcQueueMap_m ucq_map;
    uint32 cmd = 0;
    uint8 qmaptype_valid[18] = {0};
    uint16 queue_base = 0;
    uint8 index = 0;
    uint8 qmaptype = 0;
    uint8 ermprofid_uc = 0;
    uint8 ermprofid_mc = 0;
    uint8 enq_mode = 0;
    uint8 offset = 0;
    uint8 q_ofst = 0;

    CTC_ERROR_RETURN(_sys_at_queue_get_erm_profile_id(lchip, port_info->chan_id, &ermprofid_uc, &ermprofid_mc));

    for (qmaptype = 0; qmaptype < SYS_QUE_MAP_TYPE_MAX_NUM; qmaptype++)
    {
        index = qmaptype << 3 | ermprofid_uc;
        cmd = DRV_IOR(DsUcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ucq_map));
        enq_mode = GetDsUcQueueMap(V, queueOffsetMode_f, &ucq_map);
        offset = GetDsUcQueueMap(V, queueOffset_f, &ucq_map);
        q_ofst = (offset >> 2) + (offset & 0x3);
        if (SYS_AT_QUEUE_ENQ_MODE_CTL == enq_mode)
        {
            CTC_BIT_SET(qmaptype_valid[q_ofst], qmaptype);
        }
        index = qmaptype << 3 | ermprofid_mc;
        cmd = DRV_IOR(DsMcQueueMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &mcq_map));
        enq_mode = GetDsMcQueueMap(V, queueOffsetMode_f, &mcq_map);
        offset = GetDsMcQueueMap(V, queueOffset_f, &mcq_map);
        q_ofst = (offset >> 2) + (offset & 0x3);
        if (SYS_AT_QUEUE_ENQ_MODE_CTL == enq_mode)
        {
            CTC_BIT_SET(qmaptype_valid[q_ofst + 12], qmaptype);
        }
    }

    queue_base = SYS_AT_QOS_ENCOD_QBASE(port_info->sub_chan_id, port_info->pp_id, port_info->dp_id);
    for (offset = 0; offset < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN); offset++)
    {
        p_que_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_base + offset);
        if (NULL == p_que_node)
        {
            continue;
        }
        for (q_ofst = 0; q_ofst < SYS_QUEUE_SUB_NODE_NUM; q_ofst++)
        {
            _sys_at_qos_queue_map_encode_enq_mode(lchip, q_ofst, p_que_node, que_map, pos, qmaptype_valid);
        }
    }
    return CTC_E_NONE;
}


STATIC int32
_sys_at_qos_queue_map_get(uint8 lchip, ctc_qos_queue_map_t* que_map)
{
    ctc_port_bitmap_t port_bmp_zero;
    sys_port_info_t port_info;
    uint16 lport = 0;
    uint16 loop_end = 0;
    uint8 pos = 0;
    uint8 get_port = 0;
    uint8 index = 0;

    sal_memset(&port_info, 0, sizeof(sys_port_info_t));
    sal_memset(port_bmp_zero, 0, sizeof(ctc_port_bitmap_t));

    if (!sal_memcmp(que_map->port_bmp, port_bmp_zero, sizeof(ctc_port_bitmap_t)))
    {
        get_port = 1;
		lport = CTC_MAP_GPORT_TO_LPORT(que_map->gport);
		index = CTC_MAP_GPORT_TO_MCHAN_IDX(que_map->gport);
		loop_end = lport + 1;
    }
	else
	{
	    loop_end = MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP);
	}

    /*only get the first port*/
    for (; lport < loop_end; lport++)
    {
        if (!get_port && !CTC_BMP_ISSET(que_map->port_bmp, lport))
        {
            continue;
        }
        /*get port info*/
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, index, &port_info));
        if (SYS_DMPS_NETWORK_PORT != port_info.port_type && SYS_DMPS_CPUMAC_NETWORK_PORT != port_info.port_type
            && SYS_DMPS_CPU_MAC_PORT != port_info.port_type)
        {
            if(get_port)
            {
                return CTC_E_INVALID_GLOBAL_PORT;
            }
            continue;
        }
        CTC_ERROR_RETURN(_sys_at_qos_queue_map_get_enq_num(lchip, &port_info, que_map, &pos));

        /*erm profile get*/
        CTC_ERROR_RETURN(_sys_at_qos_queue_map_get_enq_mode(lchip, &port_info, que_map, &pos));
        break;
    }
    que_map->enq_num = pos;
    que_map->mode = CTC_QOS_PORT_QUEUE_FLEX_MODE;
    return CTC_E_NONE;
}

int32
sys_at_qos_queue_set(uint8 lchip, ctc_qos_queue_cfg_t* p_que_cfg, sys_cpu_reason_dest_info_t* p_dest_info)
{
    uint8 sub_queue_id = 0;
    uint8 sub_queue_id_min = 0;
    uint8 sub_queue_id_max = 0;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    switch (p_que_cfg->type)
    {
    case CTC_QOS_QUEUE_CFG_PRI_MAP:
        CTC_ERROR_RETURN(
            _sys_at_set_priority_queue_map(lchip, &p_que_cfg->value.pri_map));
        break;

    case CTC_QOS_QUEUE_CFG_QUEUE_REASON_MAP:
        {
            ctc_qos_queue_cpu_reason_map_t* p_reason_map = &p_que_cfg->value.reason_map;

            sub_queue_id = p_reason_map->reason_group * MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
            if(p_reason_map->cpu_reason == CTC_PKT_CPU_REASON_C2C_PKT)
            {
                sub_queue_id_min = sub_queue_id;
                sub_queue_id_max = sub_queue_id + MCHIP_CAP(SYS_CAP_QOS_REASON_C2C_MAX_QUEUE_NUM) - 1;
            }
            else
            {
                sub_queue_id_min = (0xff == p_reason_map->queue_id) ? sub_queue_id : sub_queue_id + p_reason_map->queue_id;
                sub_queue_id_max = (0xff == p_reason_map->queue_id) ? (sub_queue_id_min + MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) - 1) : sub_queue_id_min;
            }
            if(CTC_PKT_CPU_REASON_QUEUE_DROP_PKT == p_reason_map->cpu_reason)
            {
                uint16 reason = 0;
                uint16 sub_queue_id_tmp = 0;
                uint16 sub_queue_id_offset = 0;
                if (0xff == p_reason_map->queue_id || p_usw_queue_master[lchip]->monitor_drop_en)
                {
                    return CTC_E_INVALID_PARAM;
                }
                for (reason = 0; reason < CTC_PKT_CPU_REASON_MAX_COUNT; reason++)
                {
                    if(CTC_PKT_CPU_REASON_QUEUE_DROP_PKT == reason)
                    {
                        continue;
                    }
                    sub_queue_id_tmp = p_usw_queue_master[lchip]->cpu_reason[reason].sub_queue_id;
                    sub_queue_id_offset = CTC_IS_BIT_SET(sub_queue_id_tmp, SYS_REASON_PRI_ENQ_SHIFT) ? (MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) - 1)
                        : (reason == CTC_PKT_CPU_REASON_C2C_PKT ? (MCHIP_CAP(SYS_CAP_QOS_REASON_C2C_MAX_QUEUE_NUM) - 1) : 0);
                    if(sub_queue_id_min >= (sub_queue_id_tmp&0xff) && sub_queue_id_min <= (sub_queue_id_tmp&0xff) + sub_queue_id_offset)
                    {
                        return CTC_E_INVALID_PARAM;
                    }
                }
            }
            else if((p_usw_queue_master[lchip]->monitor_drop_en == 1)
                && p_usw_queue_master[lchip]->cpu_reason[CTC_PKT_CPU_REASON_QUEUE_DROP_PKT].sub_queue_id >= sub_queue_id_min
                && p_usw_queue_master[lchip]->cpu_reason[CTC_PKT_CPU_REASON_QUEUE_DROP_PKT].sub_queue_id <= sub_queue_id_max
                && (0xff != p_reason_map->reason_group))
            {
                return CTC_E_INVALID_PARAM;
            }
            if ((p_reason_map->reason_group < MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_BASE_EUNIT))
                 && sub_queue_id >= p_usw_queue_master[lchip]->queue_num_for_cpu_reason && (0xff != p_reason_map->reason_group))
            { /*Exceed Max Cpu Reason Group*/
                return CTC_E_INVALID_PARAM;
            }
            CTC_ERROR_RETURN(sys_usw_cpu_reason_set_map(lchip,
                                                          p_reason_map->cpu_reason,
                                                          p_reason_map->queue_id,
                                                          p_reason_map->reason_group,
                                                          p_reason_map->acl_match_group,
                                                          p_dest_info));
        }
        break;

    case CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST:
        {
            ctc_qos_queue_cpu_reason_dest_t* p_reason_dest = &p_que_cfg->value.reason_dest;
            p_dest_info->dest_type = p_reason_dest->dest_type;
            if (CTC_PKT_CPU_REASON_TO_NHID == p_reason_dest->dest_type)
            {
                p_dest_info->dest_port = p_reason_dest->nhid;
                CTC_ERROR_RETURN(sys_usw_cpu_reason_set_dest(lchip, p_reason_dest->cpu_reason, p_dest_info));
            }
            else
            {
                p_dest_info->dest_port = p_reason_dest->dest_port;
                p_dest_info->raw_dest_en = p_reason_dest->raw_dest_en;
                p_dest_info->sub_idx = p_reason_dest->sub_index;
                CTC_ERROR_RETURN(sys_usw_cpu_reason_set_dest(lchip, p_reason_dest->cpu_reason, p_dest_info));
            }
        }
        break;
    case CTC_QOS_QUEUE_CFG_QUEUE_REASON_MISC:
        CTC_ERROR_RETURN(_sys_usw_qos_set_queue_reason_misc(lchip, &p_que_cfg->value.reason_misc));
        break;
    case CTC_QOS_QUEUE_CFG_FLUSH:
        CTC_ERROR_RETURN(_sys_at_queue_set_queue_flush(lchip, &p_que_cfg->value.cfg));
        break;
    case CTC_QOS_QUEUE_CFG_QUEUE_MAP:
        CTC_ERROR_RETURN(_sys_at_qos_queue_map_set(lchip, &p_que_cfg->value.que_map));
        break;
    default:
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
sys_at_qos_queue_get(uint8 lchip, ctc_qos_queue_cfg_t* p_que_cfg)
{
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    switch (p_que_cfg->type)
    {
    case CTC_QOS_QUEUE_CFG_PRI_MAP:
        CTC_ERROR_RETURN(_sys_at_get_priority_queue_map(lchip, &p_que_cfg->value.pri_map));
        break;

    case CTC_QOS_QUEUE_CFG_QUEUE_REASON_MAP:
        {
            ctc_qos_queue_cpu_reason_map_t* p_reason_map = &p_que_cfg->value.reason_map;
            CTC_ERROR_RETURN(sys_usw_cpu_reason_get_map(lchip,p_reason_map->cpu_reason,&p_reason_map->queue_id,&p_reason_map->reason_group,&p_reason_map->acl_match_group));
        }
        break;

    case CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST:
        {
            uint16 excp_array[32] = {0};
            uint8  excp_num = 0;
            uint32 cmd         = 0;
            uint16  excp_idx = 0;
            uint8 excp_type = 0;
            uint8 idx = 0;
            EpeHdrAdjExcp_m epe_hdr_adj_excp;
            ctc_qos_queue_cpu_reason_dest_t* p_reason_dest = &p_que_cfg->value.reason_dest;
            CTC_MAX_VALUE_CHECK(p_reason_dest->cpu_reason, CTC_PKT_CPU_REASON_MAX_COUNT - 1);
            p_reason_dest->dest_type = p_usw_queue_master[lchip]->cpu_reason[p_reason_dest->cpu_reason].dest_type;
            if (CTC_PKT_CPU_REASON_TO_NHID == p_reason_dest->dest_type)
            {
                p_reason_dest->nhid = p_usw_queue_master[lchip]->cpu_reason[p_reason_dest->cpu_reason].dest_port;
            }
            else
            {
                p_reason_dest->dest_port = p_usw_queue_master[lchip]->cpu_reason[p_reason_dest->cpu_reason].dest_port;
            }
            sys_usw_queue_get_excp_idx_by_reason(lchip, p_reason_dest->cpu_reason, excp_array, &excp_num);
            for (idx = 0; idx < excp_num; idx++)
            {
                excp_type = SYS_REASON_GET_EXCP_TYPE(excp_array[idx]);

                if (excp_type != SYS_QOS_QUEUE_NORMAL_EXCP)
                {
                    continue;
                }
                excp_idx = SYS_REASON_GET_EXCP_INDEX(excp_array[idx]);
                cmd = DRV_IOR(EpeHdrAdjExcp_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_idx, cmd, &epe_hdr_adj_excp));
                p_reason_dest->raw_dest_en = (GetEpeHdrAdjExcp(V, destMapKeepMode_f, &epe_hdr_adj_excp) == 2) ? 1 : 0;
            }
        }
        break;
    case CTC_QOS_QUEUE_CFG_QUEUE_REASON_MISC:
        CTC_ERROR_RETURN(_sys_usw_qos_get_queue_reason_misc(lchip, &p_que_cfg->value.reason_misc));
        break;
    case CTC_QOS_QUEUE_CFG_QUEUE_MAP:
        CTC_ERROR_RETURN(_sys_at_qos_queue_map_get(lchip, &p_que_cfg->value.que_map));
        break;
    default:
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
    }
    return CTC_E_NONE;
}

int32
sys_at_queue_enq_init(uint8 lchip, void *p_glb_parm)
{
    int32 ret = CTC_E_NONE;
    ctc_spool_t spool;
    sys_queue_node_t  *p_queue_node = NULL;
    ctc_qos_global_cfg_t * p_glb_cfg = NULL;
    uint16 chan_num = 0;
    uint16 total_que_num = 0;
    uint16 dp_que_num = 0;
    uint16 loop = 0;

    p_glb_cfg = (ctc_qos_global_cfg_t *)p_glb_parm;

    if ((128 != p_glb_cfg->queue_num_for_cpu_reason)
        && (64 != p_glb_cfg->queue_num_for_cpu_reason)
        && (32 != p_glb_cfg->queue_num_for_cpu_reason))
    {
        return CTC_E_INVALID_PARAM;
    }

    p_usw_queue_master[lchip]->queue_num_per_chanel = MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
    p_usw_queue_master[lchip]->enq_mode = SYS_QUEUE_FIXED_MODE;

    /*************************************************
    *init queue stats base
    *************************************************/
    sys_usw_dma_get_packet_rx_chan(lchip, &chan_num);
    p_usw_queue_master[lchip]->max_dma_rx_num = chan_num;  /* must get from DMA module */
    MCHIP_CAP(SYS_CAP_CHANID_DMA_NUM) = chan_num; /*DMA channel num*/

   /*************************************************
    *init queue alloc */

    p_usw_queue_master[lchip]->queue_num_for_cpu_reason = p_glb_cfg->queue_num_for_cpu_reason;
    MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM) = p_usw_queue_master[lchip]->queue_num_for_cpu_reason;
    MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM_UC) = 32;

    /*queue num, AT:816=52*12 (Network)+128(DMAMc) + 32(DMAUc) + 128(EUNIT) per pp*/
    /* basic channel queue 312(per DP) * 8*/
    dp_que_num = MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) * MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
    total_que_num = dp_que_num * MCHIP_CAP(SYS_CAP_DP_MAX_NUM) * SYS_PP_NUM(lchip);
    MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_NETWORK_MISC) = total_que_num;
    MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) = total_que_num;
    /*DMA Queue Mc 128Q*/
    total_que_num += MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM);
    /*DMA Queue Uc 32Q*/
    total_que_num += MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM_UC);
    MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT) = total_que_num;
    /*Eunit Queue 4(GRP_NUM_EUNIT)*8(GRP_Q_NUM_EUNIT)=32Q*/
    total_que_num += (MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_NUM_EUNIT) * MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT));
    MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM) = total_que_num;

    p_usw_queue_master[lchip]->queue_vec = ctc_vector_init(total_que_num / 16, 16);
    if (NULL == p_usw_queue_master[lchip]->queue_vec)
    {
        ret = CTC_E_NO_MEMORY;
        goto error1;
    }

    for (loop = 0; loop < total_que_num; loop++)
    {
        p_queue_node = (sys_queue_node_t*)mem_malloc(MEM_QUEUE_MODULE, sizeof(sys_queue_node_t));
        if (!p_queue_node)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto error2;
        }
        sal_memset(p_queue_node, 0, sizeof(sys_queue_node_t));

        /*AT: all pp channel queue*/
        if(loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_NETWORK_MISC))
        {
            p_queue_node->type = SYS_QUEUE_TYPE_NORMAL;
            p_queue_node->offset = loop % MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
            p_queue_node->dp_id = (loop / dp_que_num) & 1;
            p_queue_node->pp_id = (loop / dp_que_num) >> 1;
            p_queue_node->sub_chan = (loop % dp_que_num) / MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
        }
        /*dma queue*/
        else if(loop >= MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) &&
                loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT))
        {
            p_queue_node->dp_id = 0;
            p_queue_node->pp_id = 0;
            p_queue_node->sub_chan = SYS_DMA_SUB_CHAN;

            if (loop >= MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM)) /*ucQ num 32*/
            {
                p_queue_node->node[0].type = SYS_QUE_OFST_UC;
                p_queue_node->type = SYS_QUEUE_TYPE_EXCP_UC;
                p_queue_node->offset = loop - (MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_REASON_TOTAL_QUEUE_NUM));
            }
            else
            {
                p_queue_node->node[0].type = SYS_QUE_OFST_MC;
                p_queue_node->type = SYS_QUEUE_TYPE_EXCP;
                p_queue_node->offset = loop - MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP);
            }
            p_queue_node->node[0].ofst = p_queue_node->offset % MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
        }
        /*AT: eunit dest id*/
        else if (loop >= MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT)
                && loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM))
        {
            p_queue_node->type = SYS_QUEUE_TYPE_EUNIT;
            p_queue_node->offset = loop - MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT);
            p_queue_node->sub_chan = SYS_DMA_SUB_CHAN;
            p_queue_node->dp_id = 0;
            if (1 == (loop - MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT)) / MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT))
            {
                p_queue_node->pp_id = 2;
            }
            else if (3 == (loop - MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT)) / MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT))
            {
                p_queue_node->pp_id = SYS_PP_NUM(lchip) / 2 + 2;
            }
            else if (2 == (loop - MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT)) / MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT))
            {
                p_queue_node->pp_id = SYS_PP_NUM(lchip) / 2 + 1;
            }
            else
            {
                p_queue_node->pp_id = 1;
            }
            p_queue_node->node[0].type = SYS_QUE_OFST_UC;
            p_queue_node->node[0].ofst = p_queue_node->offset % MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT);
            if ((p_queue_node->offset % MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT)) < SYS_AT_MC_QUEUE_NUM)
            {
                p_queue_node->node[1].type = SYS_QUE_OFST_MC;
                p_queue_node->node[1].ofst = p_queue_node->offset % MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_Q_NUM_EUNIT);
            }
        }
        p_queue_node->queue_id = loop;
        (void)ctc_vector_add(p_usw_queue_master[lchip]->queue_vec, loop, p_queue_node);
    }

    sal_memset(&spool, 0, sizeof(spool));
    spool.lchip = lchip;
    spool.block_num = CTC_VEC_BLOCK_NUM(CTC_CONST16, 4);
    spool.block_size = CTC_CONST16 / 4;
    spool.max_count = CTC_CONST16;
    spool.user_data_size = CTC_OFFSET_OF(sys_queue_enq_profile_t, calc_len);
    spool.spool_key = (hash_key_fn) _sys_at_queue_enq_profile_hash_make;
    spool.spool_cmp = (hash_cmp_fn) _sys_at_queue_enq_profile_hash_cmp;
    spool.spool_alloc = (spool_alloc_fn)_sys_at_queue_enq_profile_alloc;
    spool.spool_free = (spool_free_fn)_sys_at_queue_enq_profile_free;
    p_usw_queue_master[lchip]->enq_prof_spool = ctc_spool_create(&spool);
    if (!p_usw_queue_master[lchip]->enq_prof_spool)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error2;
    }
    CTC_ERROR_GOTO(_sys_at_queue_add_static_fix_profile(lchip), ret, error3);
    CTC_ERROR_GOTO(_sys_at_queue_reg_init(lchip), ret, error3);

    /* warmboot data restore */
    if (CTC_WB_ENABLE(lchip) && (CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        CTC_ERROR_GOTO(_sys_at_queue_wb_restore_queue_vec(lchip), ret, error3);
    }

    return CTC_E_NONE;
error3:
    ctc_spool_free(p_usw_queue_master[lchip]->enq_prof_spool);
error2:
    ctc_vector_traverse(p_usw_queue_master[lchip]->queue_vec, (vector_traversal_fn)_sys_at_queue_vec_free_node_data, NULL);
    ctc_vector_release(p_usw_queue_master[lchip]->queue_vec);
error1:

    return ret;
}

int32
sys_at_queue_enq_deinit(uint8 lchip)
{
    ctc_vector_traverse(p_usw_queue_master[lchip]->queue_vec, (vector_traversal_fn)_sys_at_queue_vec_free_node_data, NULL);
    ctc_vector_release(p_usw_queue_master[lchip]->queue_vec);
    ctc_spool_free(p_usw_queue_master[lchip]->enq_prof_spool);
    return CTC_E_NONE;
}


int32
sys_at_qos_queue_dump(uint8 lchip, uint16 start, uint16 end, uint8 detail)
{
    uint16 queue_id = 0;
    uint16 group_id = 0;
    uint8 que_offset = 0;
    uint16 channel = 0;
    uint8 pp_id = 0;
    sys_queue_node_t* p_queue_node = NULL;

    CTC_MAX_VALUE_CHECK(start, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM) - 1);
    CTC_MAX_VALUE_CHECK(end, MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM) - 1);

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "\nQueue information:\n");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-7s %-7s %-7s %-7s %-8s %-7s\n", "queue", "offset", "channel", "group","stats-en","shp-en");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "---------------------------------------------------------\n");

    for (queue_id = start; queue_id <= end && queue_id < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM); queue_id++)
    {
        p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
        if (NULL == p_queue_node)
        {
            continue;
        }
        else
        {
            que_offset = p_queue_node->offset;
        }

        pp_id = p_queue_node->pp_id;
        SYS_QOS_LCHIP_CONVERT(lchip, pp_id);
        CTC_ERROR_RETURN(sys_at_queue_get_channel_by_queue_id(lchip, queue_id, &channel));
        if (SYS_QUEUE_TYPE_NORMAL == p_queue_node->type)
        {
            SYS_AT_GROUP_ID(group_id, p_queue_node);
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-7d %-7d %-7d %-7d %-8d %-7d\n", queue_id, que_offset, channel,
                                  group_id, 1, p_queue_node->shp_en);
        }
        else
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-7d %-7d %-7d %-7s %-8d %-7d\n", queue_id, que_offset, channel,
                                  "-", 1, p_queue_node->shp_en);
        }
    }

    if (start == end)
    {
        queue_id = start;
    }

    if ((start == end) && p_queue_node)
    {
        ctc_qos_shape_queue_t que_shape;
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "\nQueue shape:\n");
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "-------------------------------\n");

        sal_memset(&que_shape, 0, sizeof(ctc_qos_shape_queue_t));
        sys_at_shape_get_que_shape_profile(lchip, queue_id, p_queue_node->offset, (void *)&que_shape);
        if (que_shape.cir)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: %d (kbps/pps)\n", "CIR", que_shape.cir);
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: %d (kb/pkt)\n", "CBS", que_shape.cbs);
        }
        else
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "No CIR Bucket, all packet always mark as yellow!\n");
        }
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: %s\n", "Shape mode", que_shape.pps_en ? "PPS" : "BPS");
        if (que_shape.enable)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: %d (kbps/pps)\n", "PIR", que_shape.pir);
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: %d (kb/pkt)\n", "PBS", que_shape.pbs);
        }
        else
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "No PIR Bucket\n");
        }
    }

    if (start == end && p_queue_node)
    {
        uint16 reason_id = 0;
        uint8 exceed_class = 0;
        uint16 exceed_weight = 0;
        uint16 sub_queue_id_min = 0;
        uint16 sub_queue_id_max = 0;

        CTC_ERROR_RETURN(sys_at_sch_get_queue_sched(lchip, queue_id, p_queue_node->offset, &exceed_class, &exceed_weight));
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "\nQueue Scheduler:\n");
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "-------------------------------\n");
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: %d \n", "Queue Class(Yellow)", exceed_class);
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: %d \n", "Weight", exceed_weight);
        if(SYS_QUEUE_TYPE_EXCP == p_queue_node->type || SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type || SYS_QUEUE_TYPE_EUNIT == p_queue_node->type)
        {
            uint8 sub_queue_id = 0;
            uint8 is_ucq = 0;
            uint8 euint = (queue_id >= MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EUNIT)) ? 1: 0;
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "\nCPU Reason:\n");
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "-------------------------------\n");
            sub_queue_id = p_queue_node->offset;
            is_ucq = SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type ? 1 : 0;
            for(reason_id = 0; reason_id < CTC_PKT_CPU_REASON_MAX_COUNT; reason_id ++)
            {
                if ((!euint && is_ucq != p_usw_queue_master[lchip]->cpu_reason[reason_id].is_uc && CTC_PKT_CPU_REASON_C2C_PKT != reason_id)
                    || (euint && p_usw_queue_master[lchip]->cpu_reason[reason_id].sub_queue_id < MCHIP_CAP(SYS_CAP_CPU_REASON_DEST_ID_BASE_EUNIT)))
                {
                    continue;
                }

                sub_queue_id_min = p_usw_queue_master[lchip]->cpu_reason[reason_id].sub_queue_id & 0xff;
                if (CTC_PKT_CPU_REASON_C2C_PKT == reason_id)
                {
                    if(is_ucq)
                    {
                        sub_queue_id_min = 2 * MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
                    }
                    sub_queue_id_max = sub_queue_id_min + MCHIP_CAP(SYS_CAP_QOS_REASON_C2C_MAX_QUEUE_NUM);
                }
                else
                {
                    sub_queue_id_max = sub_queue_id_min + (CTC_IS_BIT_SET(p_usw_queue_master[lchip]->cpu_reason[reason_id].sub_queue_id, SYS_REASON_PRI_ENQ_SHIFT) ? MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) : 1);
                }

                if(sub_queue_id >= sub_queue_id_min && sub_queue_id < sub_queue_id_max)
                {
                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: %d \n", sys_usw_reason_2Str(reason_id), reason_id);
                }
            }
        }
    }

    if (start == end && p_queue_node)
    {
        uint8 wred = 0;
        uint8 wtd  = 0;
        uint8 ofst = 0;
        ctc_qos_drop_t queu_drop;

        sal_memset(&queu_drop, 0, sizeof(ctc_qos_drop_t));

        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "\nQueue Drop:\n");
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "-------------------------------\n");

        for (ofst = 0; ofst < SYS_QUEUE_SUB_NODE_NUM; ofst++)
        {
            if (SYS_QUE_OFST_NONE == p_queue_node->node[ofst].type)
            {
                continue;
            }
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "node %d:\n", ofst);

            queu_drop.queue.class_prio = ofst;
            sys_at_resrc_get_que_drop(lchip, p_queue_node, &queu_drop, 1, &wtd, &wred);
            if (wred)
            {
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: %s\n", "Drop Mode", "WRED");
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: /%-8u/%-8u/%-8u\n", "MaxThrd",  queu_drop.drop.max_th[0], queu_drop.drop.max_th[1], queu_drop.drop.max_th[2]);
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: /%-8u/%-8u/%-8u\n", "MinThrd",  queu_drop.drop.min_th[0], queu_drop.drop.min_th[1], queu_drop.drop.min_th[2]);
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-30s: /%-8u/%-8u/%-8u \n", "Drop_prob", queu_drop.drop.drop_prob[0], queu_drop.drop.drop_prob[1], queu_drop.drop.drop_prob[2]);
            }

            sys_at_resrc_get_que_drop(lchip, p_queue_node, &queu_drop, 0, &wtd, &wred);
            if (wtd)
            {
                SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: %s\n", "Drop Mode", "WTD");
                if (queu_drop.drop.is_dynamic)
                {
                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: /%-8u/%-8u/%-8u\n",
                                        "DropFactor", queu_drop.drop.drop_factor[0], queu_drop.drop.drop_factor[1], queu_drop.drop.drop_factor[2]);
                }
                else
                {

                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: /%-8u/%-8u/%-8u\n", "DropThrd",
                                        queu_drop.drop.max_th[0], queu_drop.drop.max_th[1], queu_drop.drop.max_th[2]);
                }

                if (SYS_QUE_OFST_UC == p_queue_node->node[ofst].type)
                {
                    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s: /%-8u/%-8u/%-8u\n", "EcnThrd",
                                        queu_drop.drop.ecn_th[0], queu_drop.drop.ecn_th[1], queu_drop.drop.ecn_th[2]);
                }
            }
        }
    }

    return CTC_E_NONE;
}

int32
sys_at_qos_port_dump(uint8 lchip, uint32 start, uint32 end, uint8 detail)
{
    uint16 channel = 0;
    uint16 port = 0;
    uint8  shp_en = 0;
    uint8 is_pps = 0;
    uint32 token_rate = 0;
    uint32 token_thrd = 0;
    uint16 lport_start = 0;
    uint16 lport_end = 0;
    uint8 gchip = 0;
    uint32 gport = 0;

    gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(start);
    if (gchip != SYS_MAP_CTC_GPORT_TO_GCHIP(end))
    {
        return CTC_E_INVALID_PARAM;
    }
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(start, lchip, lport_start);
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(end, lchip, lport_end);

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "Port information:\n");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "%-10s %-10s %-10s %-15s %-15s %-7s\n","port","channel", "shp-en", "pir(kbps/pps)", "pbs(kb/pkt)","shp_mode");
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,  "-----------------------------------------------------------------\n");

    for (port = lport_start; port <= lport_end && port < SYS_USW_MAX_PORT_NUM_PER_CHIP; port++)
    {
        if (port >= SYS_INTERNAL_PORT_START && port <= SYS_INTERNAL_PORT_END)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "continue internal lport %d\n", port);
            continue;
        }
        gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, port);
        sys_at_get_channel_by_port(lchip, gport, &channel);
        sys_at_shape_get_port_shape_profile(lchip, channel, &token_rate, &token_thrd, &is_pps, &shp_en);
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%04x     %-10d %-10d %-15u %-15u %-7s\n",
                              SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, port), channel, shp_en, token_rate, token_thrd, is_pps ? "PPS" : "BPS");

        if (start == end || detail)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\nport queue info:\n");
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------\n");
            sys_at_queue_dump_port_queue_info(lchip, gport);
        }
    }
    return CTC_E_NONE;
}

#endif
